diff options
101 files changed, 2900 insertions, 9563 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam Binary files differindex 936e6886a6..9f25d31bb2 100644 --- a/bootstrap/lib/compiler/ebin/beam_asm.beam +++ b/bootstrap/lib/compiler/ebin/beam_asm.beam diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam Binary files differindex 0f44d8e4d7..4d475cd899 100644 --- a/bootstrap/lib/compiler/ebin/beam_utils.beam +++ b/bootstrap/lib/compiler/ebin/beam_utils.beam diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam Binary files differindex a92341690d..d2f4ed83bb 100644 --- a/bootstrap/lib/compiler/ebin/compile.beam +++ b/bootstrap/lib/compiler/ebin/compile.beam diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam Binary files differindex 8f4137db70..f0573bd200 100644 --- a/bootstrap/lib/compiler/ebin/core_pp.beam +++ b/bootstrap/lib/compiler/ebin/core_pp.beam diff --git a/bootstrap/lib/compiler/ebin/core_scan.beam b/bootstrap/lib/compiler/ebin/core_scan.beam Binary files differindex e9f74a1d1c..398c538178 100644 --- a/bootstrap/lib/compiler/ebin/core_scan.beam +++ b/bootstrap/lib/compiler/ebin/core_scan.beam diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam Binary files differindex c6c1593790..a1047fb87f 100644 --- a/bootstrap/lib/compiler/ebin/v3_codegen.beam +++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam Binary files differindex 6143af9050..189a8c07b2 100644 --- a/bootstrap/lib/compiler/ebin/v3_kernel.beam +++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam Binary files differindex 6b127e86d0..e1b8c58c8f 100644 --- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam +++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam Binary files differindex 4dc0ef29f2..e8a6acd235 100644 --- a/bootstrap/lib/kernel/ebin/disk_log.beam +++ b/bootstrap/lib/kernel/ebin/disk_log.beam diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam Binary files differindex 420a4e818b..bcd3c548a5 100644 --- a/bootstrap/lib/kernel/ebin/disk_log_1.beam +++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam diff --git a/bootstrap/lib/kernel/ebin/erl_boot_server.beam b/bootstrap/lib/kernel/ebin/erl_boot_server.beam Binary files differindex ef3fe6fdea..d9de814e60 100644 --- a/bootstrap/lib/kernel/ebin/erl_boot_server.beam +++ b/bootstrap/lib/kernel/ebin/erl_boot_server.beam diff --git a/bootstrap/lib/kernel/ebin/erl_reply.beam b/bootstrap/lib/kernel/ebin/erl_reply.beam Binary files differindex 6266aaa37c..d9dee00b6a 100644 --- a/bootstrap/lib/kernel/ebin/erl_reply.beam +++ b/bootstrap/lib/kernel/ebin/erl_reply.beam diff --git a/bootstrap/lib/kernel/ebin/error_logger.beam b/bootstrap/lib/kernel/ebin/error_logger.beam Binary files differindex 4129e6af6e..2415215395 100644 --- a/bootstrap/lib/kernel/ebin/error_logger.beam +++ b/bootstrap/lib/kernel/ebin/error_logger.beam diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam Binary files differindex a47aec4a2e..75064d3452 100644 --- a/bootstrap/lib/kernel/ebin/erts_debug.beam +++ b/bootstrap/lib/kernel/ebin/erts_debug.beam diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam Binary files differindex 57851fcb6e..5c5f3bfa73 100644 --- a/bootstrap/lib/kernel/ebin/group.beam +++ b/bootstrap/lib/kernel/ebin/group.beam diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam Binary files differindex ab06763c7d..6e02c48609 100644 --- a/bootstrap/lib/kernel/ebin/inet_config.beam +++ b/bootstrap/lib/kernel/ebin/inet_config.beam diff --git a/bootstrap/lib/kernel/ebin/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam Binary files differindex cebe72a7f0..8935d52e52 100644 --- a/bootstrap/lib/kernel/ebin/inet_dns.beam +++ b/bootstrap/lib/kernel/ebin/inet_dns.beam diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam Binary files differindex a5b4d7611f..cd27ee7265 100644 --- a/bootstrap/lib/kernel/ebin/inet_parse.beam +++ b/bootstrap/lib/kernel/ebin/inet_parse.beam diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam Binary files differindex 74b3a11f59..f203f7c08a 100644 --- a/bootstrap/lib/kernel/ebin/inet_res.beam +++ b/bootstrap/lib/kernel/ebin/inet_res.beam diff --git a/bootstrap/lib/kernel/ebin/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app index b888d914e8..244fad678f 100644 --- a/bootstrap/lib/kernel/ebin/kernel.app +++ b/bootstrap/lib/kernel/ebin/kernel.app @@ -120,6 +120,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-9.1", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.1", "stdlib-3.4", "sasl-3.0"]} ] }. diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam Binary files differindex 0bc6403871..cedf7bf49e 100644 --- a/bootstrap/lib/kernel/ebin/os.beam +++ b/bootstrap/lib/kernel/ebin/os.beam diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam Binary files differindex 8255fc6f82..39d80d9e36 100644 --- a/bootstrap/lib/stdlib/ebin/beam_lib.beam +++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam Binary files differindex 6840be1e57..d858a59f8b 100644 --- a/bootstrap/lib/stdlib/ebin/dets_utils.beam +++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam diff --git a/bootstrap/lib/stdlib/ebin/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam Binary files differindex b6f5e62671..1cabe095b3 100644 --- a/bootstrap/lib/stdlib/ebin/edlin.beam +++ b/bootstrap/lib/stdlib/ebin/edlin.beam diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam Binary files differindex 36c2b2219e..22c0978854 100644 --- a/bootstrap/lib/stdlib/ebin/epp.beam +++ b/bootstrap/lib/stdlib/ebin/epp.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam Binary files differindex dc4c689263..d018b33132 100644 --- a/bootstrap/lib/stdlib/ebin/erl_lint.beam +++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam Binary files differindex e77e0f9136..5c5a46d8bb 100644 --- a/bootstrap/lib/stdlib/ebin/erl_pp.beam +++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam Binary files differindex 86307bc790..d36202515a 100644 --- a/bootstrap/lib/stdlib/ebin/erl_scan.beam +++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam Binary files differindex 30dea42a21..10982c84ce 100644 --- a/bootstrap/lib/stdlib/ebin/escript.beam +++ b/bootstrap/lib/stdlib/ebin/escript.beam diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam Binary files differindex 40be147afa..c2b113b79e 100644 --- a/bootstrap/lib/stdlib/ebin/ets.beam +++ b/bootstrap/lib/stdlib/ebin/ets.beam diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam Binary files differindex f2a1fd74d0..74c7c5ce01 100644 --- a/bootstrap/lib/stdlib/ebin/file_sorter.beam +++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam diff --git a/bootstrap/lib/stdlib/ebin/filename.beam b/bootstrap/lib/stdlib/ebin/filename.beam Binary files differindex a94acbb852..13f1c8029e 100644 --- a/bootstrap/lib/stdlib/ebin/filename.beam +++ b/bootstrap/lib/stdlib/ebin/filename.beam diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam Binary files differindex e85995c1de..c02da85965 100644 --- a/bootstrap/lib/stdlib/ebin/io_lib_format.beam +++ b/bootstrap/lib/stdlib/ebin/io_lib_format.beam diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam Binary files differindex 6ad7dff7da..98a7f91ab8 100644 --- a/bootstrap/lib/stdlib/ebin/lib.beam +++ b/bootstrap/lib/stdlib/ebin/lib.beam diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam Binary files differindex 912dfba644..166574e0f6 100644 --- a/bootstrap/lib/stdlib/ebin/otp_internal.beam +++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam Binary files differindex 4a315e8d42..592f7b4740 100644 --- a/bootstrap/lib/stdlib/ebin/qlc.beam +++ b/bootstrap/lib/stdlib/ebin/qlc.beam diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam Binary files differindex ac343d8abd..1a7d678227 100644 --- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam +++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam Binary files differindex a0e2b73018..fab94d5509 100644 --- a/bootstrap/lib/stdlib/ebin/shell.beam +++ b/bootstrap/lib/stdlib/ebin/shell.beam diff --git a/bootstrap/lib/stdlib/ebin/slave.beam b/bootstrap/lib/stdlib/ebin/slave.beam Binary files differindex 299c24448d..abab0acf33 100644 --- a/bootstrap/lib/stdlib/ebin/slave.beam +++ b/bootstrap/lib/stdlib/ebin/slave.beam diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam Binary files differindex a2cc62d4af..aa8ed3d99c 100644 --- a/bootstrap/lib/stdlib/ebin/sofs.beam +++ b/bootstrap/lib/stdlib/ebin/sofs.beam diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam Binary files differindex a281027902..8bb21b24f2 100644 --- a/bootstrap/lib/stdlib/ebin/string.beam +++ b/bootstrap/lib/stdlib/ebin/string.beam diff --git a/erts/emulator/beam/erl_io_queue.c b/erts/emulator/beam/erl_io_queue.c index a01b676d39..190ba6bbb9 100644 --- a/erts/emulator/beam/erl_io_queue.c +++ b/erts/emulator/beam/erl_io_queue.c @@ -973,9 +973,10 @@ static int iol2v_append_binary(iol2v_state_t *state, Eterm bin_term) { UWord binary_size; Uint byte_offset, bit_offset, bit_size; + byte *binary_data; + Eterm *parent_header; Eterm parent_binary; - byte *binary_data; ASSERT(state->bytereds_available > state->bytereds_spent); @@ -1001,14 +1002,14 @@ static int iol2v_append_binary(iol2v_state_t *state, Eterm bin_term) { erts_emasculate_writable_binary(pb); } - binary_data = pb->bytes; + binary_data = &((byte*)pb->bytes)[byte_offset]; } else { ErlHeapBin *hb = (ErlHeapBin*)parent_header; ASSERT(thing_subtag(*parent_header) == HEAP_BINARY_SUBTAG); ASSERT(is_bin_small); - binary_data = &((unsigned char*)&hb->data)[byte_offset]; + binary_data = &((byte*)&hb->data)[byte_offset]; } if (!is_bin_small && (state->acc_size == 0 || !is_acc_small)) { diff --git a/erts/emulator/test/emulator_smoke.spec b/erts/emulator/test/emulator_smoke.spec index b2d0de8835..fc98ba6823 100644 --- a/erts/emulator/test/emulator_smoke.spec +++ b/erts/emulator/test/emulator_smoke.spec @@ -7,3 +7,4 @@ [consistency],"Not reliable in October and March"}. {cases,'Dir',crypto_SUITE,[t_md5]}. {cases,'Dir',float_SUITE,[fpe,cmp_integer]}. +{cases,'Dir',erts_debug_SUITE,[df]}. diff --git a/erts/emulator/test/iovec_SUITE.erl b/erts/emulator/test/iovec_SUITE.erl index 28df36d293..49dc64b0d2 100644 --- a/erts/emulator/test/iovec_SUITE.erl +++ b/erts/emulator/test/iovec_SUITE.erl @@ -24,7 +24,8 @@ -export([integer_lists/1, binary_lists/1, empty_lists/1, empty_binary_lists/1, mixed_lists/1, improper_lists/1, illegal_lists/1, cons_bomb/1, - iolist_to_iovec_idempotence/1, iolist_to_iovec_correctness/1]). + sub_binary_lists/1, iolist_to_iovec_idempotence/1, + iolist_to_iovec_correctness/1]). -include_lib("common_test/include/ct.hrl"). @@ -34,8 +35,8 @@ suite() -> all() -> [integer_lists, binary_lists, empty_lists, empty_binary_lists, mixed_lists, - illegal_lists, improper_lists, cons_bomb, iolist_to_iovec_idempotence, - iolist_to_iovec_correctness]. + sub_binary_lists, illegal_lists, improper_lists, cons_bomb, + iolist_to_iovec_idempotence, iolist_to_iovec_correctness]. init_per_suite(Config) -> Config. @@ -46,15 +47,16 @@ end_per_suite(Config) -> integer_lists(Config) when is_list(Config) -> Variations = gen_variations([I || I <- lists:seq(1, 255)]), + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - - ok. +sub_binary_lists(Config) when is_list(Config) -> + Parent = <<0:256/unit:8, "gazurka">>, + <<0:196/unit:8, Child/binary>> = Parent, + equivalence_test(fun erlang:iolist_to_iovec/1, gen_variations(Child)). binary_lists(Config) when is_list(Config) -> Variations = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). empty_lists(Config) when is_list(Config) -> Variations = gen_variations([[] || _ <- lists:seq(1, 256)]), @@ -70,8 +72,7 @@ empty_binary_lists(Config) when is_list(Config) -> mixed_lists(Config) when is_list(Config) -> Variations = gen_variations([<<>>, lists:seq(1, 40), <<12, 45, 78>>]), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). illegal_lists(Config) when is_list(Config) -> BitStrs = gen_variations(["gurka", <<1:1>>, "gaffel"]), @@ -82,18 +83,15 @@ illegal_lists(Config) when is_list(Config) -> Variations = BitStrs ++ BadInts ++ Atoms ++ BadTails, - illegality_test(fun erlang:iolist_to_iovec/1, Variations), - - ok. + illegality_test(fun erlang:iolist_to_iovec/1, Variations). improper_lists(Config) when is_list(Config) -> Variations = [ [[[[1 | <<2>>] | <<3>>] | <<4>>] | <<5>>], - [[<<"test">>, 3] | <<"improper tail">>], - [1, 2, 3 | <<"improper tail">>] + [[<<1>>, 2] | <<3, 4, 5>>], + [1, 2, 3 | <<4, 5>>] ], - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). cons_bomb(Config) when is_list(Config) -> IntBase = gen_variations([I || I <- lists:seq(1, 255)]), @@ -108,8 +106,7 @@ cons_bomb(Config) when is_list(Config) -> end, Variations = gen_variations([IntBase, BinBase, MixBase], Rounds), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). iolist_to_iovec_idempotence(Config) when is_list(Config) -> IntVariations = gen_variations([I || I <- lists:seq(1, 255)]), @@ -134,11 +131,15 @@ iolist_to_iovec_correctness(Config) when is_list(Config) -> ok. illegality_test(Fun, Variations) -> - [{'EXIT',{badarg, _}} = (catch Fun(Variation)) || Variation <- Variations]. + [{'EXIT',{badarg, _}} = (catch Fun(Variation)) || Variation <- Variations], + ok. equivalence_test(Fun, [Head | _] = Variations) -> + %% Check that each variation is equal to the others, and that the sum of + %% them is equal to the input. Comparand = Fun(Head), - [is_iolist_equal(Comparand, Fun(Variation)) || Variation <- Variations], + [true = is_iolist_equal(Comparand, Fun(V)) || V <- Variations], + true = is_iolist_equal(Variations, Fun(Variations)), ok. is_iolist_equal(A, B) -> diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src index 430a4fa2fb..0aa4aacf16 100644 --- a/lib/common_test/src/common_test.app.src +++ b/lib/common_test/src/common_test.app.src @@ -92,7 +92,7 @@ "sasl-2.4.2", "snmp-5.1.2", "ssh-4.0", - "stdlib-2.5", + "stdlib-3.4", "syntax_tools-1.7", "tools-2.8", "xmerl-1.3.8" diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src index 446f2b9882..37a41c1a56 100644 --- a/lib/debugger/src/debugger.app.src +++ b/lib/debugger/src/debugger.app.src @@ -48,5 +48,5 @@ ]}, {registered, [dbg_iserver, dbg_wx_mon, dbg_wx_winman]}, {applications, [kernel, stdlib]}, - {runtime_dependencies, ["wx-1.2","stdlib-2.5","kernel-3.0","erts-6.0", + {runtime_dependencies, ["wx-1.2","stdlib-3.4","kernel-5.3","erts-9.0", "compiler-5.0"]}]}. diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src index 5f803875b0..e3a0fc967d 100644 --- a/lib/dialyzer/src/dialyzer.app.src +++ b/lib/dialyzer/src/dialyzer.app.src @@ -48,6 +48,6 @@ {registered, []}, {applications, [compiler, hipe, kernel, stdlib, wx]}, {env, []}, - {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.0", - "kernel-5.0","hipe-3.15.4","erts-8.0", + {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.4", + "kernel-5.3","hipe-3.16.1","erts-9.0", "compiler-7.0"]}]}. diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml index c9b74a9ec5..62e958870e 100644 --- a/lib/diameter/doc/src/diameter_sctp.xml +++ b/lib/diameter/doc/src/diameter_sctp.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd" [ + <!ENTITY man_tcp_sender + '<seealso marker="diameter_tcp#sender">diameter_tcp(3)</seealso>'> <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> <!ENTITY gen_sctp_open1 '<seealso marker="kernel:gen_sctp#open-1">gen_sctp:open/1</seealso>'> @@ -78,7 +80,11 @@ and implements the behaviour documented in <v>Reason = term()</v> <v>OwnOpt = {raddr, &ip_address;} | {rport, integer()} - | {accept, Match}</v> + | {accept, Match} + | {unordered, boolean() | pos_integer()} + | {packet, boolean() | raw} + | {message_cb, &mod_eval;} + | {sender, boolean()}</v> <v>SctpOpt = term()</v> <v>Match = &ip_address; | string() | [Match]</v> </type> @@ -106,6 +112,41 @@ A string-valued <c>Match</c> that does not parse as an address is interpreted as a regular expression.</p> <p> +Option <c>unordered</c> specifies whether or not to use unordered +delivery, integer <c>N</c> being equivalent to <c>N =< OS</c>, +where <c>OS</c> is the number of outbound streams negotiated on the +association in question. +Regardless of configuration, sending is ordered on stream 0 +until reception of a second incoming message, to ensure that a peer +receives capabilities exchange messages before any other. +Defaults to <c>false</c>.</p> + +<p> +Option <c>packet</c> determines how/if an incoming message is +packaged into a diameter_packet record. +If <c>false</c> then messages are received as binary(). +If <c>true</c> then as a record with the binary() message in the +<c>bin</c> field and a <c>{stream, Id}</c> tuple in the +<c>transport_data</c> field, where <c>Id</c> is the identifier of the +inbound stream the message was received on. +If <c>raw</c> then as a record with the received ancillary +sctp_sndrcvinfo record in the <c>transport_data</c> field. +Defaults to <c>true</c>.</p> + +<p> +Options <c>message_cb</c> and <c>sender</c> have semantics identical +to those documented in &man_tcp_sender;, but with the message argument +to a <c>recv</c> callback being as directed by the <c>packet</c> +option.</p> + +<p> +An <c>{outstream, Id}</c> tuple in the <c>transport_data</c> field of +a outgoing diameter_packet record sets the outbound stream on which +the message is sent, modulo the negotiated number of outbound streams. +Any other value causes successive such sends to cycle though all +outbound streams.</p> + +<p> Remaining options are any accepted by &gen_sctp_open1;, with the exception of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c> and <c>sctp_events</c>. @@ -121,29 +162,16 @@ connecting transport.</p> <warning> <p> -An insufficiently large receive buffer may result in a peer having to +An small receive buffer may result in a peer having to resend incoming messages: set the &inet; option <c>recbuf</c> to increase the buffer size.</p> <p> -An insufficiently large send buffer may result in outgoing messages +An small send buffer may result in outgoing messages being discarded: set the &inet; option <c>sndbuf</c> to increase the buffer size.</p> </warning> -<p> -The <c>transport_data</c> field of record <c>diameter_packet</c> -is used to communicate the stream on which an inbound message -has been received, or on which an outbound message should be sent. -The value will be of the form <c>{stream, Id}</c> for an inbound -message passed to a &app_handle_request; or &app_handle_answer; -callback. -For an outbound message, <c>{outstream, Id}</c> in the return value of -&app_handle_request; or &app_prepare_retransmit; sets the outbound -stream, the stream id being interpreted modulo the number of outbound -streams. -Any other value, or not setting a value, causes successive such sends -to cycle though all outbound streams.</p> </desc> </func> diff --git a/lib/diameter/doc/src/diameter_soc.xml b/lib/diameter/doc/src/diameter_soc.xml index ae404fcda4..28e01ff1be 100644 --- a/lib/diameter/doc/src/diameter_soc.xml +++ b/lib/diameter/doc/src/diameter_soc.xml @@ -1,15 +1,22 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd" [ + <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> + <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'> + <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'> + <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'> + <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'> + <!ENTITY NA '—'> + <!ENTITY BR '<br/> <br/>'> <!ENTITY % also SYSTEM "seealso.ent" > %also; ]> -<chapter xmlns:xi="http://www.w3.org/2001/XInclude"> +<chapter> <header> <copyright> <year>2011</year> -<year>2016</year> +<year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> @@ -41,63 +48,1285 @@ limitations under the License. </header> <p> -Known points of questionable or non-compliance.</p> +The table below summarizes the diameter application's compliance with +&the_rfc;. +Since the diameter application isn't a Diameter node on its own, +compliance is strictly the responsibility of the user in many cases, +diameter providing the means for the user to be compliant +rather than being compliant on its own.</p> -<!-- ===================================================================== --> - -<section> -<title>&the_rfc;</title> - -<list> - -<item> -<p> -There is no support for DTLS over SCTP.</p> -</item> - -<item> <p> -There is no explicit support for peer discovery (section 5.2). -It can possibly be implemented on top of diameter as is but this is -probably something that diameter should do.</p> -</item> +The Compliance column notes <em>C</em> (Compliant) if the required +functionality is implemented, <em>PC</em> (Partially Compliant) if +there are limitations, <em>NC</em> (Not Compliant) if functionality is +not implemented, or a dash if text is informational or only places +requirements that must be met by the user's implementation.</p> -<item> <p> -The peer state machine's election process (section 5.6.4) isn't -implemented as specified since it assumes knowledge of a -peer's Origin-Host before sending it a CER. (The identity becoming known -upon reception of CEA.) -The possibility of configuring -the peer's Origin-Host could be added, along with handling of the case -that it sends something else, but for many applications this will -just be unnecessary configuration of a value that it has no control over.</p> -</item> -<!-- Transport protocol plus address/port, which we do know when - sending and receiving CER, is enough to definitely identify - the peer. However, there's nothing stopping a peer from using - different identities on different transport protocols, even - if it's maybe a bit far-fetched. --> - -</list> - -<xi:include href="diameter_soc_rfc6733.xml"/> - -</section> +Capitalized <em>Diameter</em> refers to the protocol, lowercase +<em>diameter</em> to the Erlang application.</p> <!-- ===================================================================== --> <section> -<title>RFC 3539</title> +<title>&the_rfc; - Diameter Base Protocol</title> -<p> -RFC 3539 is more difficult to comply to since it discusses -problems as much as it requires functionality but all the MUST's are -covered, the watchdog state machine being the primary one. -Of the optional functionality, load balancing is left to the -diameter user (since it's the one deciding who to send to) and -there is no Congestion Manager.</p> +<table> +<row> + <cell><em>Section</em></cell> + <cell><em>Title</em></cell> + <cell><em>Compliance</em></cell> + <cell><em>Notes</em></cell> +</row> +<row> + <cell>1</cell> + <cell>Introduction</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1</cell> + <cell>Diameter Protocol</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.1</cell> + <cell>Description of the Document Set</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.2</cell> + <cell>Conventions Used in This Document</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.3</cell> + <cell>Changes from RFC 3588</cell> + <cell>&NA;</cell> + <cell>It is possible to configure a 3588 dictionary in + order to get 3588 semantics, where the differ from 6733.</cell> +</row> +<row> + <cell>1.2</cell> + <cell>Terminology</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.3</cell> + <cell>Approach to Extensibility</cell> + <cell>&NA;</cell> + <cell>The dictionary interface documented in &man_dict; provides + extensibility, allowing the user to defined new AVPs, commands, and + applications. + Ready dictionaries are provided for the &the_rfc; common message, base + accounting, and relay applications, as well as for RFC 7683, + Diameter Overload Indicator Conveyance.</cell> +</row> +<row> + <cell>1.3.1</cell> + <cell>Defining New AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.3.2</cell> + <cell>Creating New AVPs</cell> + <cell>&NA;</cell> + <cell>New AVPs can be defined using the dictionary interface. + Both both RFC data formats and extensions are supported.</cell> +</row> +<row> + <cell>1.3.3</cell> + <cell>Creating New Commands</cell> + <cell>&NA;</cell> + <cell>New commands can be defined using the dictionary interface.</cell> +</row> +<row> + <cell>1.3.4</cell> + <cell>Creating New Diameter Applications</cell> + <cell>&NA;</cell> + <cell>New applications can be defined using the dictionary interface.</cell> +</row> +<row> + <cell>2</cell> + <cell>Protocol Overview</cell> + <cell>&NA;</cell> + <cell>Session state is the responsibility of the user.&BR; + The role of a Diameter node is determined by the user's + implementation.</cell> +</row> +<row> + <cell>2.1</cell> + <cell>Transport</cell> + <cell>PC</cell> + <cell>Ports are configured by the user: diameter places no + restrictions.&BR; + The transport interface documented in &man_transport; + allows the user to implement their own methods. + Ready support is provided for TCP, TCP/TLS, and SCTP, but not + DTLS/SCTP.&BR; + Multiple connections to the same peer is possible. + ICMP messages are not interpreted.</cell> +</row> +<row> + <cell>2.1.1</cell> + <cell>SCTP Guidelines</cell> + <cell>C</cell> + <cell>Unordered sending is configurable in &man_sctp;. + There is no special handling of DPR/DPA: since a user that cares + about pending answers should wait for them before initiating + DPR.&BR; + A PPID can be configured with a a gen_sctp sctp_default_send_param + option.</cell> +</row> +<row> + <cell>2.2</cell> + <cell>Securing Diameter Messages</cell> + <cell>PC</cell> + <cell>DTLS is not supported by &man_sctp;. See also + 2.1.</cell> +</row> +<row> + <cell>2.3</cell> + <cell>Diameter Application Compliance</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>2.4</cell> + <cell>Application Identifiers</cell> + <cell>C</cell> + <cell>The user configures diameter with the identifiers to send at + capabilities exchange, along with corresponding dictionaries + defining the messages of the applications.</cell> +</row> +<row> + <cell>2.5</cell> + <cell>Connections vs. Sessions</cell> + <cell>C</cell> + <cell>Connections are realized by configuring transport. Sessions + are the responsibility of the user.</cell> +</row> +<row> + <cell>2.6</cell> + <cell>Peer Table</cell> + <cell>PC</cell> + <cell>Routing is implemented by the user in callbacks documented in + &man_app;. + A peer table of the documented form is not exposed to the user.</cell> +</row> +<row> + <cell>2.7</cell> + <cell>Routing Table</cell> + <cell>PC</cell> + <cell>See 2.6. + A routing table of the documented form is not exposed to + the user.</cell> +</row> +<row> + <cell>2.8</cell> + <cell>Role of Diameter Agents</cell> + <cell>C</cell> + <cell>Most role-specific behaviour is implemented by the user. + How a node advertises itself at capabilities exchange is determined + by user configuration.</cell> +</row> +<row> + <cell>2.8.1</cell> + <cell>Relay Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.2</cell> + <cell>Proxy Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.3</cell> + <cell>Redirect Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.4</cell> + <cell>Translation Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.9</cell> + <cell>Diameter Path Authorization</cell> + <cell>&NA;</cell> + <cell>Authorization is the responsibility of the user.</cell> +</row> +<row> + <cell>3</cell> + <cell>Diameter Header</cell> + <cell>C</cell> + <cell>Hop-by-Hop and End-to-End Identifiers are set by diameter when + sending outgoing requests.</cell> +</row> +<row> + <cell>3.1</cell> + <cell>Command Codes</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>3.2</cell> + <cell>Command Code Format Specification</cell> + <cell>C</cell> + <cell>Commands are defined as CCF specifications in dictionary + files.</cell> +</row> +<row> + <cell>3.3</cell> + <cell>Diameter Command Naming Conventions</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>4</cell> + <cell>Diameter AVPs</cell> + <cell>C</cell> + <cell>Any required padding is added by diameter when encoding + outgoing messages.</cell> +</row> +<row> + <cell>4.1</cell> + <cell>AVP Header</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.1.1</cell> + <cell>Optional Header Elements</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.2</cell> + <cell>Basic AVP Data Formats</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.3</cell> + <cell>Derived AVP Data Formats</cell> + <cell>C</cell> + <cell>Arbitrary derived data formats are supported by the dictionary + interface.</cell> +</row> +<row> + <cell>4.3.1</cell> + <cell>Common Derived AVP Data Formats</cell> + <cell>C</cell> + <cell>Beware that RFC 6733 changed the DiameterURI transport/port + defaults specified in RFC3588. + Relying on the defaults can result in interoperability + problems.</cell> +</row> +<row> + <cell>4.4</cell> + <cell>Grouped AVP Values</cell> + <cell>C</cell> + <cell>The M-bit on a component AVP of a Grouped AVP that does not + set M is ignored: such AVPs are not regarded as erroneous at + decode.&BR; + Grouped AVPs are defined as CCF specifications in dictionary + files.</cell> +</row> +<row> + <cell>4.4.1</cell> + <cell>Example AVP with a Grouped Data Type</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>4.5</cell> + <cell>Diameter Base Protocol AVPs</cell> + <cell>C</cell> + <cell>The base AVPs are defined in the common dictionary provided by + diameter. + There are common dictionaries for both RFC 3588 and RFC 6733 since + the latter made changes to both syntax and semantics.</cell> +</row> +<row> + <cell>5</cell> + <cell>Diameter Peers</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.1</cell> + <cell>Peer Connections</cell> + <cell>PC</cell> + <cell>A peer's DiameterIdentity is not required when initiating a + connection: the identify is received at capabilities exchange, at + which time the connection can be rejected if the identity is + objectionable.&BR; + The number of connections established depends on the user's + configuration. Multiple connections per peer is possible.</cell> +</row> +<row> + <cell>5.2</cell> + <cell>Diameter Peer Discovery</cell> + <cell>NC</cell> + <cell>No form of peer discovery is implemented. + The user can implement this independently of diameter if + required.</cell> +</row> +<row> + <cell>5.3</cell> + <cell>Capabilities Exchange</cell> + <cell>C</cell> + <cell>All supported applications are sent in CEA. + The user can reject an incoming CER or CEA in a configured + callback.&BR; + Both transport security at connection establishment and + negotiated via an Inband-Security AVP are supported.</cell> +</row> +<row> + <cell>5.3.1</cell> + <cell>Capabilities-Exchange-Request</cell> + <cell>C</cell> + <cell>CER is sent and received by diameter.</cell> +</row> +<row> + <cell>5.3.2</cell> + <cell>Capabilities-Exchange-Answer</cell> + <cell>C</cell> + <cell>CEA is sent and received by diameter.</cell> +</row> +<row> + <cell>5.3.3</cell> + <cell>Vendor-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.4</cell> + <cell>Firmware-Revision AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.5</cell> + <cell>Host-IP-Address AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.6</cell> + <cell>Supported-Vendor-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.7</cell> + <cell>Product-Name AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.4</cell> + <cell>Disconnecting Peer Connections</cell> + <cell>C</cell> + <cell>DPA will not be answered with error: a peer that wants to a + avoid a race can wait for pending answers before sending + DPR.</cell> +</row> +<row> + <cell>5.4.1</cell> + <cell>Disconnect-Peer-Request</cell> + <cell>C</cell> + <cell>DPR is sent by diameter in response to configuration + changes requiring a connection to be broken. + The user can also send DPR.</cell> +</row> +<row> + <cell>5.4.2</cell> + <cell>Disconnect-Peer-Answer</cell> + <cell>C</cell> + <cell>DPR is answered by diameter.</cell> +</row> +<row> + <cell>5.4.3</cell> + <cell>Disconnect-Cause AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.5</cell> + <cell>Transport Failure Detection</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.5.1</cell> + <cell>Device-Watchdog-Request</cell> + <cell>C</cell> + <cell>DWR is sent and received by diameter. + Callbacks notify the user of transitions into and out of the OKAY + state.</cell> +</row> +<row> + <cell>5.5.2</cell> + <cell>Device-Watchdog-Answer</cell> + <cell>C</cell> + <cell>DWA is sent and received by diameter.</cell> +</row> +<row> + <cell>5.5.3</cell> + <cell>Transport Failure Algorithm</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.5.4</cell> + <cell>Failover and Failback Procedures</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.6</cell> + <cell>Peer State Machine</cell> + <cell>PC</cell> + <cell>The election process is modified as described in 5.6.4.</cell> +</row> +<row> + <cell>5.6.1</cell> + <cell>Incoming Connections</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.6.2</cell> + <cell>Events</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.6.3</cell> + <cell>Actions</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.6.4</cell> + <cell>The Election Process</cell> + <cell>PC</cell> + <cell>As documented, the election assumes knowledge of a peer's + DiameterIdentity when initiating a connection, which diameter + doesn't require. Connections will be accepted if configuration + allows multiple connections per peer to be established or there is + no existing connection. Note that the election process is only + applicable when multiple connections per peer is + disallowed.</cell> +</row> +<row> + <cell>6</cell> + <cell>Diameter Message Processing</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>6.1</cell> + <cell>Diameter Request Routing Overview</cell> + <cell>&NA;</cell> + <cell>Routing is performed by the user. + A callback from diameter provides a list of available suitable peer + connections.</cell> +</row> +<row> + <cell>6.1.1</cell> + <cell>Originating a Request</cell> + <cell>C</cell> + <cell>Requests are constructed by the user; diameter sets header + fields as defined in the relevant dictionary.</cell> +</row> +<row> + <cell>6.1.2</cell> + <cell>Sending a Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.1.3</cell> + <cell>Receiving Requests</cell> + <cell>C</cell> + <cell>Loops are detected by diameter when the return value of a + request callback asks that a request be forwarded. + Loop detection in other cases is the responsibility of the + user.</cell> +</row> +<row> + <cell>6.1.4</cell> + <cell>Processing Local Requests</cell> + <cell>C</cell> + <cell>The user decides whether or not to process a request locally + in the request callback from diameter.</cell> +</row> +<row> + <cell>6.1.5</cell> + <cell>Request Forwarding</cell> + <cell>PC</cell> + <cell>See 2.6.</cell> +</row> +<row> + <cell>6.1.6</cell> + <cell>Request Routing</cell> + <cell>PC</cell> + <cell>See 2.7.</cell> +</row> +<row> + <cell>6.1.7</cell> + <cell>Predictive Loop Avoidance</cell> + <cell>C</cell> + <cell>See 6.1.3.</cell> +</row> +<row> + <cell>6.1.8</cell> + <cell>Redirecting Requests</cell> + <cell>PC</cell> + <cell>See 2.6.</cell> +</row> +<row> + <cell>6.1.9</cell> + <cell>Relaying and Proxying Requests</cell> + <cell>C</cell> + <cell>A Route-Record AVP is appended by diameter when the return + value of a request callback asks that a request be forwarded. + Appending the AVP in other cases is the responsibility of the + user.</cell> +</row> +<row> + <cell>6.2</cell> + <cell>Diameter Answer Processing</cell> + <cell>C</cell> + <cell>Answer message are constructed by the user, except in the case + of some protocol errors, in which case the procedures are + followed.</cell> +</row> +<row> + <cell>6.2.1</cell> + <cell>Processing Received Answers</cell> + <cell>C</cell> + <cell>Answers with an unknown Hop-by-Hop Identifier are + discarded.</cell> +</row> +<row> + <cell>6.2.2</cell> + <cell>Relaying and Proxying Answers</cell> + <cell>&NA;</cell> + <cell>Modifying answers is the responsibility of the user in + callbacks from diameter.</cell> +</row> +<row> + <cell>6.3</cell> + <cell>Origin-Host AVP</cell> + <cell>C</cell> + <cell>The order of AVPs in an encoded message is determined by + the CCF of the message in question.&BR; + AVPs defined in the RFC are defined in dictionaries provided by + diameter. + Their proper use in application messages is the responsibility of + the user.</cell> +</row> +<row> + <cell>6.4</cell> + <cell>Origin-Realm AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.5</cell> + <cell>Destination-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.6</cell> + <cell>Destination-Realm AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7</cell> + <cell>Routing AVPs</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>6.7.1</cell> + <cell>Route-Record AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.2</cell> + <cell>Proxy-Info AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.3</cell> + <cell>Proxy-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.4</cell> + <cell>Proxy-State AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.8</cell> + <cell>Auth-Application-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.9</cell> + <cell>Acct-Application-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.10</cell> + <cell>Inband-Security-Id AVP</cell> + <cell>C</cell> + <cell>See 2.1.</cell> +</row> +<row> + <cell>6.11</cell> + <cell>Vendor-Specific-Application-Id AVP</cell> + <cell>C</cell> + <cell>Note that the CCF of this AVP is not the same as in RFC + 3588.</cell> +</row> +<row> + <cell>6.12</cell> + <cell>Redirect-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.13</cell> + <cell>Redirect-Host-Usage AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.14</cell> + <cell>Redirect-Max-Cache-Time AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7</cell> + <cell>Error Handling</cell> + <cell>C</cell> + <cell>Answers are formulated by the user in most cases. + Answers setting the E-bit can be sent by diameter itself in response + to a request that cannot be handled by the user.</cell> +</row> +<row> + <cell>7.1</cell> + <cell>Result-Code AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.1</cell> + <cell>Informational</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.2</cell> + <cell>Success</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.3</cell> + <cell>Protocol Errors</cell> + <cell>C</cell> + <cell>Result codes 3001, 3002, 3005, and 3007 can be sent in answers + formulated by diameter, if configured to do so.</cell> +</row> +<row> + <cell>7.1.4</cell> + <cell>Transient Failures</cell> + <cell>C</cell> + <cell>Result code 4003 is sent in CEA if there is an existing + connection to the peer in question and configuration does not allow + more than one.</cell> +</row> +<row> + <cell>7.1.5</cell> + <cell>Permanent Failures</cell> + <cell>C</cell> + <cell>Message reception detects 5001, 5004, + 5005, 5008, 5009, 5010, 5011, 5014, 5015, and 5017 errors. + It ignores 5013 errors at the admonition of sections 3 and 4.1.&BR; + Note that RFC 3588 did not allow 5xxx result codes in + answers setting the E-bit, while RFC 6733 does. + This is a potential interoperability problem since the Diameter + protocol version has not changed.</cell> +</row> +<row> + <cell>7.2</cell> + <cell>Error Bit</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.3</cell> + <cell>Error-Message AVP</cell> + <cell>C</cell> + <cell>The user can include this AVP as required.</cell> +</row> +<row> + <cell>7.4</cell> + <cell>Error-Reporting-Host AVP</cell> + <cell>C</cell> + <cell>The user can include this AVP as required.</cell> +</row> +<row> + <cell>7.5</cell> + <cell>Failed-AVP AVP</cell> + <cell>C</cell> + <cell>The user constructs application-specific messages, but + diameter provides failed AVPs in message callbacks. Failed component AVPs + are grouped within the relevant Grouped AVPs.</cell> +</row> +<row> + <cell>7.6</cell> + <cell>Experimental-Result AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.7</cell> + <cell>Experimental-Result-Code AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8</cell> + <cell>Diameter User Sessions</cell> + <cell>&NA;</cell> + <cell>Authorization and accounting AVPs are defined in provided + dictionaries. Their proper use is the responsibility of the + user.</cell> +</row> +<row> + <cell>8.1</cell> + <cell>Authorization Session State Machine</cell> + <cell>&NA;</cell> + <cell>Authorization is the responsibility of the user: diameter does + not implement this state machine.</cell> +</row> +<row> + <cell>8.2</cell> + <cell>Accounting Session State Machine</cell> + <cell>&NA;</cell> + <cell>Accounting is the responsibility of the user: diameter does + not implement this state machine.</cell> +</row> +<row> + <cell>8.3</cell> + <cell>Server-Initiated Re-Auth</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>8.3.1</cell> + <cell>Re-Auth-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.3.2</cell> + <cell>Re-Auth-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.4</cell> + <cell>Session Termination</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.4.1</cell> + <cell>Session-Termination-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.4.2</cell> + <cell>Session-Termination-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.5</cell> + <cell>Aborting a Session</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.5.1</cell> + <cell>Abort-Session-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.5.2</cell> + <cell>Abort-Session-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.6</cell> + <cell>Inferring Session Termination from Origin-State-Id</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.7</cell> + <cell>Auth-Request-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.8</cell> + <cell>Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.9</cell> + <cell>Authorization-Lifetime AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.10</cell> + <cell>Auth-Grace-Period AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.11</cell> + <cell>Auth-Session-State AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.12</cell> + <cell>Re-Auth-Request-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.13</cell> + <cell>Session-Timeout AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.14</cell> + <cell>User-Name AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.15</cell> + <cell>Termination-Cause AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.16</cell> + <cell>Origin-State-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.17</cell> + <cell>Session-Binding AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.18</cell> + <cell>Session-Server-Failover AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.19</cell> + <cell>Multi-Round-Time-Out AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.20</cell> + <cell>Class AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.21</cell> + <cell>Event-Timestamp AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9</cell> + <cell>Accounting</cell> + <cell>&NA;</cell> + <cell>Accounting-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>9.1</cell> + <cell>Server Directed Model</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.2</cell> + <cell>Protocol Messages</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.3</cell> + <cell>Accounting Application Extension and Requirements</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.4</cell> + <cell>Fault Resilience</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.5</cell> + <cell>Accounting Records</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.6</cell> + <cell>Correlation of Accounting Records</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.7</cell> + <cell>Accounting Command Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.7.1</cell> + <cell>Accounting-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.7.2</cell> + <cell>Accounting-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8</cell> + <cell>Accounting AVPs</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.8.1</cell> + <cell>Accounting-Record-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.2</cell> + <cell>Acct-Interim-Interval AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.3</cell> + <cell>Accounting-Record-Number AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.4</cell> + <cell>Acct-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.5</cell> + <cell>Acct-Multi-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.6</cell> + <cell>Accounting-Sub-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.7</cell> + <cell>Accounting-Realtime-Required AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>10</cell> + <cell>AVP Occurrence Tables</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>10.1</cell> + <cell>Base Protocol Command AVP Table</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>10.2</cell> + <cell>Accounting AVP Table</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11</cell> + <cell>IANA Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1</cell> + <cell>AVP Header</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1.1</cell> + <cell>AVP Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1.2</cell> + <cell>AVP Flags</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2</cell> + <cell>Diameter Header</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2.1</cell> + <cell>Command Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2.2</cell> + <cell>Command Flags</cell> + <cell></cell> + <cell></cell> +</row> +<row> + <cell>11.3</cell> + <cell>AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.1</cell> + <cell>Experimental-Result-Code AVP</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.2</cell> + <cell>Result-Code AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.3</cell> + <cell>Accounting-Record-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.4</cell> + <cell>Termination-Cause AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.5</cell> + <cell>Redirect-Host-Usage AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.6</cell> + <cell>Session-Server-Failover AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.7</cell> + <cell>Session-Binding AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.8</cell> + <cell>Disconnect-Cause AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.9</cell> + <cell>Auth-Request-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.10</cell> + <cell>Auth-Session-State AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.11</cell> + <cell>Re-Auth-Request-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.12</cell> + <cell>Accounting-Realtime-Required AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.13</cell> + <cell>Inband-Security-Id AVP (code 299)</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.4</cell> + <cell>_diameters Service Name and Port Number Registration</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.5</cell> + <cell>SCTP Payload Protocol Identifiers</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.6</cell> + <cell>S-NAPTR Parameters</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>12</cell> + <cell>Diameter Protocol-Related Configurable Parameters</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>13</cell> + <cell>Security Considerations</cell> + <cell>PC</cell> + <cell>See 2.1.&BR; + IPsec is transparent to diameter.</cell> +</row> +<row> + <cell>13.1</cell> + <cell>TLS/TCP and DTLS/SCTP Usage</cell> + <cell>PC</cell> + <cell>See 2.1.</cell> +</row> +<row> + <cell>13.2</cell> + <cell>Peer-to-Peer Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>13.3</cell> + <cell>AVP Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14</cell> + <cell>References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14.1</cell> + <cell>Normative References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14.2</cell> + <cell>Informative References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> + +<tcaption>RFC 6733 Compliance</tcaption> +</table> </section> </chapter> + +<!-- LocalWords: AVP AVPs CCF DiameterIdentity CEA CER Inband IP +--> +<!-- LocalWords: DPA DPR DWR DWA Failover Failback Proxying Auth +--> +<!-- LocalWords: interoperability Multi Timestamp Realtime +--> diff --git a/lib/diameter/doc/src/diameter_soc_rfc6733.xml b/lib/diameter/doc/src/diameter_soc_rfc6733.xml deleted file mode 100644 index 2098965706..0000000000 --- a/lib/diameter/doc/src/diameter_soc_rfc6733.xml +++ /dev/null @@ -1,8693 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<!-- - -<copyright> -<year>2013</year><year>2016</year> -<holder>Ericsson AB. All Rights Reserved.</holder> -</copyright> - -<legalnotice> -Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -</legalnotice> - ---> - -<!DOCTYPE section SYSTEM "chapter.dtd" [ - <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> - <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'> - <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'> - <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'> - <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'> - <!ENTITY nada '<p>No comment.</p>'> - <!ENTITY % also SYSTEM "seealso.ent" > - %also; -]> - -<section> -<title>Commentary</title> - -<p> -A more detailed commentary on &the_rfc; follows. -Its purpose is to (hopefully) clarify not only what is supported but -how, given that semantics and features discussed in the RFC are not -solely the responsibility of the diameter application: -in many cases much depends on the configuration a user passes to -diameter, the implementation of &man_app; callback modules in -particular.</p> - -<p> -Comments apply to all text following the preceding comment. -Be sure to distinguish between capitalized <em>Diameter</em>, the -protocol defined by the RFC, and lowercase <em>diameter</em>, the -Erlang application to which the commentary applies.</p> - -<warning> -<p> -The commentary is not yet complete. -Comments currently stop at chapter 4.</p> -</warning> - -<pre> -Fajardo, et al. Standards Track [Page 6] - -RFC 6733 Diameter Base Protocol October 2012 - - -1. Introduction - - Authentication, Authorization, and Accounting (AAA) protocols such as - TACACS [RFC1492] and RADIUS [RFC2865] were initially deployed to - provide dial-up PPP [RFC1661] and terminal server access. Over time, - AAA support was needed on many new access technologies, the scale and - complexity of AAA networks grew, and AAA was also used on new - applications (such as voice over IP). This led to new demands on AAA - protocols. -</pre> - -<p> -Note that diameter implements the Diameter protocol as defined in -&the_rfc;. -It also supported the previous version of the protocol, as defined in -RFC 3588, when there are differences. -(Which will be noted below.) -It does not support RADIUS.</p> - -<pre> - - Network access requirements for AAA protocols are summarized in - Aboba, et al. [RFC2989]. These include: - - Failover - - [RFC2865] does not define failover mechanisms and, as a result, - failover behavior differs between implementations. In order to - provide well-defined failover behavior, Diameter supports - application-layer acknowledgements and defines failover algorithms - and the associated state machine. -</pre> - -&nada; - -<pre> - - Transmission-level security - - RADIUS [RFC2865] defines an application-layer authentication and - integrity scheme that is required only for use with response - packets. While [RFC2869] defines an additional authentication and - integrity mechanism, use is only required during Extensible - Authentication Protocol (EAP) [RFC3748] sessions. While attribute - hiding is supported, [RFC2865] does not provide support for per- - packet confidentiality. In accounting, [RFC2866] assumes that - replay protection is provided by the backend billing server rather - than within the protocol itself. - - While [RFC3162] defines the use of IPsec with RADIUS, support for - IPsec is not required. In order to provide universal support for - transmission-level security, and enable both intra- and inter- - domain AAA deployments, Diameter provides support for TLS/TCP and - DTLS/SCTP. Security is discussed in Section 13. -</pre> - -<p> -Whether or not IPsec is used is transparent to diameter.</p> - -<p> -The transport protocol used on a given peer connection is also -transparent to diameter in that transport to diameter is simply a -module that implements the transport protocol documented in -&man_transport;. -A diameter user configures this module as the &mod_transport_opt; -<c>transport_module</c>.</p> - -<p> -While a user can implement their own transport modules, diameter -includes implementations for TCP and SCTP: -&man_tcp; based on &gen_tcp; and &man_sctp; based on &gen_sctp;. -The former supports TLS but the latter does not currently support -DTLS.</p> - -<pre> - - Reliable transport - - RADIUS runs over UDP, and does not define retransmission behavior; - as a result, reliability varies between implementations. As - described in [RFC2975], this is a major issue in accounting, where - packet loss may translate directly into revenue loss. In order to - - - - - - -Fajardo, et al. Standards Track [Page 7] - -RFC 6733 Diameter Base Protocol October 2012 - - - provide well-defined transport behavior, Diameter runs over - reliable transport mechanisms (TCP, Stream Control Transmission - Protocol (SCTP)) as defined in [RFC3539]. - - Agent support - - RADIUS does not provide for explicit support for agents, including - proxies, redirects, and relays. Since the expected behavior is - not defined, it varies between implementations. Diameter defines - agent behavior explicitly; this is described in Section 2.8. -</pre> - -&nada; - -<pre> - - Server-initiated messages - - While server-initiated messages are defined in RADIUS [RFC5176], - support is optional. This makes it difficult to implement - features such as unsolicited disconnect or re-authentication/ - re-authorization on demand across a heterogeneous deployment. To - address this issue, support for server-initiated messages is - mandatory in Diameter. -</pre> - -<p> -A diameter user can both send and receive messages.</p> - -<pre> - - Transition support - - While Diameter does not share a common protocol data unit (PDU) - with RADIUS, considerable effort has been expended in enabling - backward compatibility with RADIUS so that the two protocols may - be deployed in the same network. Initially, it is expected that - Diameter will be deployed within new network devices, as well as - within gateways enabling communication between legacy RADIUS - devices and Diameter agents. This capability enables Diameter - support to be added to legacy networks, by addition of a gateway - or server speaking both RADIUS and Diameter. -</pre> - -<p> -RADIUS Attributes can be redefined as Diameter AVP's using diameter's -&man_dict; interface but diameter provides no such definitions.</p> - -<pre> - - In addition to addressing the above requirements, Diameter also - provides support for the following: - - Capability negotiation - - RADIUS does not support error messages, capability negotiation, or - a mandatory/non-mandatory flag for attributes. Since RADIUS - clients and servers are not aware of each other's capabilities, - they may not be able to successfully negotiate a mutually - acceptable service or, in some cases, even be aware of what - service has been implemented. Diameter includes support for error - handling (Section 7), capability negotiation (Section 5.3), and - mandatory/non-mandatory Attribute-Value Pairs (AVPs) - (Section 4.1). - - - - - -Fajardo, et al. Standards Track [Page 8] - -RFC 6733 Diameter Base Protocol October 2012 - - - Peer discovery and configuration - - RADIUS implementations typically require that the name or address - of servers or clients be manually configured, along with the - corresponding shared secrets. This results in a large - administrative burden and creates the temptation to reuse the - RADIUS shared secret, which can result in major security - vulnerabilities if the Request Authenticator is not globally and - temporally unique as required in [RFC2865]. Through DNS, Diameter - enables dynamic discovery of peers (see Section 5.2). Derivation - of dynamic session keys is enabled via transmission-level - security. - - Over time, the capabilities of Network Access Server (NAS) devices - have increased substantially. As a result, while Diameter is a - considerably more sophisticated protocol than RADIUS, it remains - feasible to implement it within embedded devices. -</pre> - -&nada; - -<pre> - -1.1. Diameter Protocol - - The Diameter base protocol provides the following facilities: - - o Ability to exchange messages and deliver AVPs -</pre> - -<p> -There are two interfaces directly involved in message exchange when -using diameter: the function &mod_call; for sending outgoing requests, -and the application callback interface, documented in &man_app; for -receiving incoming request and answers.</p> - -<pre> - - o Capabilities negotiation -</pre> - -<p> -Capabilities negotiation is the responsibility of diameter: -a user configures a diameter service and/or transport with -&capabilities; to provide AVP values for CER and CEA messages but it -is diameter itself that sends these messages. -A user receives notification of a successful capabilities exchange by -way of &app_peer_up; callbacks.</p> - -<pre> - - o Error notification -</pre> - -<p> -A user can subscribe to &events;, using &mod_subscribe;, in order to -receive notification of various failures. -Errors in Diameter messaging are communicated via the application -callbacks &app_handle_request;, &app_handle_answer; and -&app_handle_error;.</p> - - -<pre> - - o Extensibility, required in [RFC2989], through addition of new - applications, commands, and AVPs -</pre> - -<p> -Support for applications, commands and AVP's is extensible using -diameter's dictionary interface, as documented in &man_dict;. -Dictionaries are compiled to Erlang encode/decode modules using -&man_compile; or &man_make;.</p> - -<pre> - - o Basic services necessary for applications, such as the handling of - user sessions or accounting -</pre> - -<p> -Compiled dictionaries are provided for the RFC 3588 and RFC 6733 -Diameter applications: common, base accounting and relay. -Dictionaries for a number of standardized -applications are provided in uncompiled form below the <c>examples</c> -subdirectory of the diameter application directory.</p> - -<pre> - - All data delivered by the protocol is in the form of AVPs. Some of - these AVP values are used by the Diameter protocol itself, while - others deliver data associated with particular applications that - employ Diameter. AVPs may be arbitrarily added to Diameter messages, - the only restriction being that the Command Code Format (CCF) - specification (Section 3.2) be satisfied. AVPs are used by the base - Diameter protocol to support the following required features: - - o Transporting of user authentication information, for the purposes - of enabling the Diameter server to authenticate the user - - o Transporting of service-specific authorization information, - between client and servers, allowing the peers to decide whether a - user's access request should be granted - - - -Fajardo, et al. Standards Track [Page 9] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Exchanging resource usage information, which may be used for - accounting purposes, capacity planning, etc. - - o Routing, relaying, proxying, and redirecting of Diameter messages - through a server hierarchy - - The Diameter base protocol satisfies the minimum requirements for a - AAA protocol, as specified by [RFC2989]. The base protocol may be - used by itself for accounting purposes only, or it may be used with a - Diameter application, such as Mobile IPv4 [RFC4004], or network - access [RFC4005]. It is also possible for the base protocol to be - extended for use in new applications, via the addition of new - commands or AVPs. The initial focus of Diameter was network access - and accounting applications. A truly generic AAA protocol used by - many applications might provide functionality not provided by - Diameter. Therefore, it is imperative that the designers of new - applications understand their requirements before using Diameter. - See Section 1.3.4 for more information on Diameter applications. - - Any node can initiate a request. In that sense, Diameter is a peer- - to-peer protocol. In this document, a Diameter client is a device at - the edge of the network that performs access control, such as a - Network Access Server (NAS) or a Foreign Agent (FA). A Diameter - client generates Diameter messages to request authentication, - authorization, and accounting services for the user. A Diameter - agent is a node that does not provide local user authentication or - authorization services; agents include proxies, redirects, and relay - agents. A Diameter server performs authentication and/or - authorization of the user. A Diameter node may act as an agent for - certain requests while acting as a server for others. - - The Diameter protocol also supports server-initiated messages, such - as a request to abort service to a particular user. -</pre> - -&nada; - -<pre> - -1.1.1. Description of the Document Set - - The Diameter specification consists of an updated version of the base - protocol specification (this document) and the Transport Profile - [RFC3539]. This document obsoletes both RFC 3588 and RFC 5719. A - summary of the base protocol updates included in this document can be - found in Section 1.1.3. - - This document defines the base protocol specification for AAA, which - includes support for accounting. There are also a myriad of - applications documents describing applications that use this base - specification for Authentication, Authorization, and Accounting. - These application documents specify how to use the Diameter protocol - within the context of their application. - - - -Fajardo, et al. Standards Track [Page 10] - -RFC 6733 Diameter Base Protocol October 2012 - - - The Transport Profile document [RFC3539] discusses transport layer - issues that arise with AAA protocols and recommendations on how to - overcome these issues. This document also defines the Diameter - failover algorithm and state machine. - - "Clarifications on the Routing of Diameter Request Based on the - Username and the Realm" [RFC5729] defines specific behavior on how to - route requests based on the content of the User-Name AVP (Attribute - Value Pair). - -1.1.2. Conventions Used in This Document - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in [RFC2119]. -</pre> - -&nada; - -<pre> - -1.1.3. Changes from RFC 3588 - - This document obsoletes RFC 3588 but is fully backward compatible - with that document. The changes introduced in this document focus on - fixing issues that have surfaced during the implementation of - Diameter (RFC 3588). An overview of some the major changes are given - below. -</pre> - -<p> -RFC 6733 is not fully backwards compatible with RFC 3588. -(For example, in what values of Result-Code values are permissible with -the E-bit.) -The implications of incompatibilities for diameter are noted where -appropriate.</p> - -<pre> - - o Deprecated the use of the Inband-Security AVP for negotiating - Transport Layer Security (TLS) [RFC5246]. It has been generally - considered that bootstrapping of TLS via Inband-Security AVP - creates certain security risks because it does not completely - protect the information carried in the CER/CEA (Capabilities- - Exchange-Request/Capabilities-Exchange-Answer). This version of - Diameter adopts the common approach of defining a well-known - secured port that peers should use when communicating via TLS/TCP - and DTLS/SCTP. This new approach augments the existing in-band - security negotiation, but it does not completely replace it. The - old method is kept for backward compatibility reasons. -</pre> - -<p> -&man_tcp; supports both methods of negotiating TLS: -bootstrapping via Inband-Security and directly following connection -establishment.</p> - -<pre> - - o Deprecated the exchange of CER/CEA messages in the open state. - This feature was implied in the peer state machine table of RFC - 3588, but it was not clearly defined anywhere else in that - document. As work on this document progressed, it became clear - that the multiplicity of meaning and use of Application-Id AVPs in - the CER/CEA messages (and the messages themselves) is seen as an - abuse of the Diameter extensibility rules and thus required - simplification. Capabilities exchange in the open state has been - re-introduced in a separate specification [RFC6737], which clearly - defines new commands for this feature. -</pre> - -<p> -Capabilities exchange in the open state is not supported: an incoming -CER in the open state will cause diameter to ask the relevant -transport process to terminate, which implies the loss of the peer -connection in the case of &man_tcp; and &man_sctp;.</p> - -<p> -Capabilities update, as defined by RFC 6737, is not yet supported. -Support will require diameter to handle CUR/CUA in the same way that -it handles CER/CEA.</p> - -<pre> - - - - - -Fajardo, et al. Standards Track [Page 11] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Simplified security requirements. The use of a secured transport - for exchanging Diameter messages remains mandatory. However, TLS/ - TCP and DTLS/SCTP have become the primary methods of securing - Diameter with IPsec as a secondary alternative. See Section 13 - for details. The support for the End-to-End security framework - (E2E-Sequence AVP and 'P'-bit in the AVP header) has also been - deprecated. -</pre> - -<p> -The End-to-End security framework is not supported since it's use is -largely unspecified: diameter will set the P-bit in outgoing AVP's as -directed by the relevant dictionary and/or &app_prepare_request; or -&app_handle_request; callbacks, but whether or not the P-bit is set on -incoming AVP's has no consequence.</p> - -<p> -As noted above, DTLS is not currently supported and whether or not -IPsec is used is transparent to diameter.</p> - -<pre> - - o Changed Diameter extensibility. This includes fixes to the - Diameter extensibility description (Section 1.3 and others) to - better aid Diameter application designers; in addition, the new - specification relaxes the policy with respect to the allocation of - Command Codes for vendor-specific uses. - - o Clarified Application Id usage. Clarify the proper use of - Application Id information, which can be found in multiple places - within a Diameter message. This includes correlating Application - Ids found in the message headers and AVPs. These changes also - clearly specify the proper Application Id value to use for - specific base protocol messages (ASR/ASA, STR/STA) as well as - clarify the content and use of Vendor-Specific-Application-Id. - - o Clarified routing fixes. This document more clearly specifies - what information (AVPs and Application Ids) can be used for making - general routing decisions. A rule for the prioritization of - redirect routing criteria when multiple route entries are found - via redirects has also been added (see Section 6.13). - - o Simplified Diameter peer discovery. The Diameter discovery - process now supports only widely used discovery schemes; the rest - have been deprecated (see Section 5.2 for details). -</pre> - -<p> -Peer discover is not currently supported: peers to which a node should -connect must be configured. -Connection requests are accepted from arbitrary peers but a -&mod_transport_opt; <c>capabilities_cb</c> can be used to reject a -peer based on an incoming CER or CEA.</p> - -<pre> - - There are many other miscellaneous fixes that have been introduced in - this document that may not be considered significant, but they have - value nonetheless. Examples are removal of obsolete types, fixes to - the state machine, clarification of the election process, message - validation, fixes to Failed-AVP and Result-Code AVP values, etc. All - of the errata filed against RFC 3588 prior to the publication of this - document have been addressed. A comprehensive list of changes is not - shown here for practical reasons. - -1.2. Terminology - - AAA - - Authentication, Authorization, and Accounting. - - - - - -Fajardo, et al. Standards Track [Page 12] - -RFC 6733 Diameter Base Protocol October 2012 - - - ABNF - - Augmented Backus-Naur Form [RFC5234]. A metalanguage with its own - formal syntax and rules. It is based on the Backus-Naur Form and - is used to define message exchanges in a bi-directional - communications protocol. - - Accounting - - The act of collecting information on resource usage for the - purpose of capacity planning, auditing, billing, or cost - allocation. - - Accounting Record - - An accounting record represents a summary of the resource - consumption of a user over the entire session. Accounting servers - creating the accounting record may do so by processing interim - accounting events or accounting events from several devices - serving the same user. - - Authentication - - The act of verifying the identity of an entity (subject). - - Authorization - - The act of determining whether a requesting entity (subject) will - be allowed access to a resource (object). - - Attribute-Value Pair (AVP) - - The Diameter protocol consists of a header followed by one or more - Attribute-Value-Pairs (AVPs). An AVP includes a header and is - used to encapsulate protocol-specific data (e.g., routing - information) as well as authentication, authorization, or - accounting information. -</pre> - -&nada; - -<pre> - - Command Code Format (CCF) - - A modified form of ABNF used to define Diameter commands (see - Section 3.2). -</pre> - -<p> -The <c>@messages</c> section of the &man_dict; format has the CCF as -content.</p> - -<pre> - - Diameter Agent - - A Diameter Agent is a Diameter node that provides relay, proxy, - redirect, or translation services. - - - - -Fajardo, et al. Standards Track [Page 13] - -RFC 6733 Diameter Base Protocol October 2012 - - - Diameter Client - - A Diameter client is a Diameter node that supports Diameter client - applications as well as the base protocol. Diameter clients are - often implemented in devices situated at the edge of a network and - provide access control services for that network. Typical - examples of Diameter clients include the Network Access Server - (NAS) and the Mobile IP Foreign Agent (FA). - - Diameter Node - - A Diameter node is a host process that implements the Diameter - protocol and acts as either a client, an agent, or a server. - - Diameter Peer - - Two Diameter nodes sharing a direct TCP or SCTP transport - connection are called Diameter peers. - - Diameter Server - - A Diameter server is a Diameter node that handles authentication, - authorization, and accounting requests for a particular realm. By - its very nature, a Diameter server must support Diameter server - applications in addition to the base protocol. -</pre> - -<p> -A Diameter Node is implemented by configuring a service -using &mod_start_service; and one or more transports using -&mod_add_transport;. -The service typically represents a Diameter Node but since -capabilities can be configured on individual transports it's more -accurate to say that the node is a collection of transports -advertising the same Origin-Host.</p> - -<p> -The role of a node (agent, client or server) is not something that's -configured explicitly. -Transports are either connecting or listening, depending on whether -diameter should establish a peer connection and send CER or accept -connections and receive CER, but the role a node implements depends -largely on dictionary configuration and &man_app; callback -implementation.</p> - -<pre> - - Downstream - - Downstream is used to identify the direction of a particular - Diameter message from the home server towards the Diameter client. - - Home Realm - - A Home Realm is the administrative domain with which the user - maintains an account relationship. - - Home Server - - A Diameter server that serves the Home Realm. - - Interim Accounting - - An interim accounting message provides a snapshot of usage during - a user's session. Typically, it is implemented in order to - provide for partial accounting of a user's session in case a - device reboot or other network problem prevents the delivery of a - session summary message or session record. - - - - -Fajardo, et al. Standards Track [Page 14] - -RFC 6733 Diameter Base Protocol October 2012 - - - Local Realm - - A local realm is the administrative domain providing services to a - user. An administrative domain may act as a local realm for - certain users while being a home realm for others. - - Multi-session - - A multi-session represents a logical linking of several sessions. - Multi-sessions are tracked by using the Acct-Multi-Session-Id. An - example of a multi-session would be a Multi-link PPP bundle. Each - leg of the bundle would be a session while the entire bundle would - be a multi-session. - - Network Access Identifier - - The Network Access Identifier, or NAI [RFC4282], is used in the - Diameter protocol to extract a user's identity and realm. The - identity is used to identify the user during authentication and/or - authorization while the realm is used for message routing - purposes. - - Proxy Agent or Proxy - - In addition to forwarding requests and responses, proxies make - policy decisions relating to resource usage and provisioning. - Typically, this is accomplished by tracking the state of NAS - devices. While proxies usually do not respond to client requests - prior to receiving a response from the server, they may originate - Reject messages in cases where policies are violated. As a - result, proxies need to understand the semantics of the messages - passing through them, and they may not support all Diameter - applications. - - Realm - - The string in the NAI that immediately follows the '@' character. - NAI realm names are required to be unique and are piggybacked on - the administration of the DNS namespace. Diameter makes use of - the realm, also loosely referred to as domain, to determine - whether messages can be satisfied locally or whether they must be - routed or redirected. In RADIUS, realm names are not necessarily - piggybacked on the DNS namespace but may be independent of it. - - - - - - - - -Fajardo, et al. Standards Track [Page 15] - -RFC 6733 Diameter Base Protocol October 2012 - - - Real-Time Accounting - - Real-time accounting involves the processing of information on - resource usage within a defined time window. Typically, time - constraints are imposed in order to limit financial risk. The - Diameter Credit-Control Application [RFC4006] is an example of an - application that defines real-time accounting functionality. - - Relay Agent or Relay - - Relays forward requests and responses based on routing-related - AVPs and routing table entries. Since relays do not make policy - decisions, they do not examine or alter non-routing AVPs. As a - result, relays never originate messages, do not need to understand - the semantics of messages or non-routing AVPs, and are capable of - handling any Diameter application or message type. Since relays - make decisions based on information in routing AVPs and realm - forwarding tables, they do not keep state on NAS resource usage or - sessions in progress. - - Redirect Agent - - Rather than forwarding requests and responses between clients and - servers, redirect agents refer clients to servers and allow them - to communicate directly. Since redirect agents do not sit in the - forwarding path, they do not alter any AVPs transiting between - client and server. Redirect agents do not originate messages and - are capable of handling any message type, although they may be - configured only to redirect messages of certain types, while - acting as relay or proxy agents for other types. As with relay - agents, redirect agents do not keep state with respect to sessions - or NAS resources. -</pre> - -&nada; - -<pre> - - Session - - A session is a related progression of events devoted to a - particular activity. Diameter application documents provide - guidelines as to when a session begins and ends. All Diameter - packets with the same Session-Id are considered to be part of the - same session. -</pre> - -<p> -Sessions are not something that diameter is aware of. -The function &mod_session_id; can be used to construct appropriate -values for Session-Id AVP's but logic connecting events in the same -session is the responsibility of the diameter user.</p> - -<pre> - - Stateful Agent - - A stateful agent is one that maintains session state information, - by keeping track of all authorized active sessions. Each - authorized session is bound to a particular service, and its state - is considered active either until it is notified otherwise or - until expiration. - - - -Fajardo, et al. Standards Track [Page 16] - -RFC 6733 Diameter Base Protocol October 2012 - - - Sub-session - - A sub-session represents a distinct service (e.g., QoS or data - characteristics) provided to a given session. These services may - happen concurrently (e.g., simultaneous voice and data transfer - during the same session) or serially. These changes in sessions - are tracked with the Accounting-Sub-Session-Id. - - Transaction State - - The Diameter protocol requires that agents maintain transaction - state, which is used for failover purposes. Transaction state - implies that upon forwarding a request, the Hop-by-Hop Identifier - is saved; the field is replaced with a locally unique identifier, - which is restored to its original value when the corresponding - answer is received. The request's state is released upon receipt - of the answer. A stateless agent is one that only maintains - transaction state. - - Translation Agent - - A translation agent (TLA in Figure 4) is a stateful Diameter node - that performs protocol translation between Diameter and another - AAA protocol, such as RADIUS. - - Upstream - - Upstream is used to identify the direction of a particular - Diameter message from the Diameter client towards the home server. - - User - - The entity or device requesting or using some resource, in support - of which a Diameter client has generated a request. -</pre> - -&nada; - -<pre> - -1.3. Approach to Extensibility - - The Diameter protocol is designed to be extensible, using several - mechanisms, including: - - o Defining new AVP values - - o Creating new AVPs - - o Creating new commands - - o Creating new applications - - - - -Fajardo, et al. Standards Track [Page 17] - -RFC 6733 Diameter Base Protocol October 2012 - - - From the point of view of extensibility, Diameter authentication, - authorization, and accounting applications are treated in the same - way. -</pre> - -<p> -Extensibility in diameter is by way of the dictionary interface -documented in &man_dict;: a diameter user creates applications, -commands and AVP's by implementing a new dictionary, -compiling the dictionary to a codec module using &man_compile; or -&man_make;, and configuring the resulting dictionary module on a -service. -The dictionary modules provided with diameter are all implemented in -this manner.</p> - -<pre> - Note: Protocol designers should try to reuse existing functionality, - namely AVP values, AVPs, commands, and Diameter applications. Reuse - simplifies standardization and implementation. To avoid potential - interoperability issues, it is important to ensure that the semantics - of the reused features are well understood. Given that Diameter can - also carry RADIUS attributes as Diameter AVPs, such reuse - considerations also apply to existing RADIUS attributes that may be - useful in a Diameter application. -</pre> - -<p> -Reuse in dictionary files is achieved by way of the <c>@inherits</c> -section. -AVP's are inherited, commands are not.</p> - -<pre> - -1.3.1. Defining New AVP Values - - In order to allocate a new AVP value for AVPs defined in the Diameter - base protocol, the IETF needs to approve a new RFC that describes the - AVP value. IANA considerations for these AVP values are discussed in - Section 11.3. - - The allocation of AVP values for other AVPs is guided by the IANA - considerations of the document that defines those AVPs. Typically, - allocation of new values for an AVP defined in an RFC would require - IETF Review [RFC5226], whereas values for vendor-specific AVPs can be - allocated by the vendor. - -1.3.2. Creating New AVPs - - A new AVP being defined MUST use one of the data types listed in - Sections 4.2 or 4.3. If an appropriate derived data type is already - defined, it SHOULD be used instead of a base data type to encourage - reusability and good design practice. - - In the event that a logical grouping of AVPs is necessary, and - multiple "groups" are possible in a given command, it is recommended - that a Grouped AVP be used (see Section 4.4). - - The creation of new AVPs can happen in various ways. The recommended - approach is to define a new general-purpose AVP in a Standards Track - RFC approved by the IETF. However, as described in Section 11.1.1, - there are other mechanisms. -</pre> - -<p> -Creating new AVP's is an issue for the dictionary designer, not -diameter.</p> - -<pre> - -1.3.3. Creating New Commands - - A new Command Code MUST be allocated when required AVPs (those - indicated as {AVP} in the CCF definition) are added to, deleted from, - or redefined in (for example, by changing a required AVP into an - optional one) an existing command. - - - -Fajardo, et al. Standards Track [Page 18] - -RFC 6733 Diameter Base Protocol October 2012 - - - Furthermore, if the transport characteristics of a command are - changed (for example, with respect to the number of round trips - required), a new Command Code MUST be registered. - - A change to the CCF of a command, such as described above, MUST - result in the definition of a new Command Code. This subsequently - leads to the need to define a new Diameter application for any - application that will use that new command. - - The IANA considerations for Command Codes are discussed in - Section 3.1. -</pre> - -<p> -Creating new commands is an issue for the dictionary designer, not -diameter.</p> - -<pre> - -1.3.4. Creating New Diameter Applications - - Every Diameter application specification MUST have an IANA-assigned - Application Id (see Section 2.4). The managed Application ID space - is flat, and there is no relationship between different Diameter - applications with respect to their Application Ids. As such, there - is no versioning support provided by these Application Ids - themselves; every Diameter application is a standalone application. - If the application has a relationship with other Diameter - applications, such a relationship is not known to Diameter. -</pre> - -<p> -Creating new applications is an issue for the dictionary designer, -not diameter.</p> - -<p> -An application's Application Id is specified in the <c>@id</c> section -of a dictionary file.</p> - -<pre> - - Before describing the rules for creating new Diameter applications, - it is important to discuss the semantics of the AVP occurrences as - stated in the CCF and the M-bit flag (Section 4.1) for an AVP. There - is no relationship imposed between the two; they are set - independently. - - o The CCF indicates what AVPs are placed into a Diameter command by - the sender of that command. Often, since there are multiple modes - of protocol interactions, many of the AVPs are indicated as - optional. - - o The M-bit allows the sender to indicate to the receiver whether or - not understanding the semantics of an AVP and its content is - mandatory. If the M-bit is set by the sender and the receiver - does not understand the AVP or the values carried within that AVP, - then a failure is generated (see Section 7). -</pre> - -<p> -The M-bit is set on outgoing AVP's as directed by the relevant -dictionary. -For incoming AVP's, an M-bit set on an AVP that isn't -explicitly included in the definition of the command in question is -interpreted as a 5001 error, DIAMETER_AVP_UNSUPPORTED, the -consequences of which depend on the value of the &mod_application_opt; -<c>answer_errors</c> or <c>request_errors</c>.</p> - -<pre> - - It is the decision of the protocol designer when to develop a new - Diameter application rather than extending Diameter in other ways. - However, a new Diameter application MUST be created when one or more - of the following criteria are met: - - - - - - - -Fajardo, et al. Standards Track [Page 19] - -RFC 6733 Diameter Base Protocol October 2012 - - - M-bit Setting - - An AVP with the M-bit in the MUST column of the AVP flag table is - added to an existing Command/Application. An AVP with the M-bit - in the MAY column of the AVP flag table is added to an existing - Command/Application. - - Note: The M-bit setting for a given AVP is relevant to an - Application and each command within that application that includes - the AVP. That is, if an AVP appears in two commands for - application Foo and the M-bit settings are different in each - command, then there should be two AVP flag tables describing when - to set the M-bit. - - Commands - - A new command is used within the existing application because - either an additional command is added, an existing command has - been modified so that a new Command Code had to be registered, or - a command has been deleted. - - AVP Flag bits - - If an existing application changes the meaning/semantics of its - AVP Flags or adds new flag bits, then a new Diameter application - MUST be created. - - If the CCF definition of a command allows it, an implementation may - add arbitrary optional AVPs with the M-bit cleared (including vendor- - specific AVPs) to that command without needing to define a new - application. Please refer to Section 11.1.1 for details. -</pre> - -&nada; - -<pre> - -2. Protocol Overview - - The base Diameter protocol concerns itself with establishing - connections to peers, capabilities negotiation, how messages are sent - and routed through peers, and how the connections are eventually torn - down. The base protocol also defines certain rules that apply to all - message exchanges between Diameter nodes. - - Communication between Diameter peers begins with one peer sending a - message to another Diameter peer. The set of AVPs included in the - message is determined by a particular Diameter application. One AVP - that is included to reference a user's session is the Session-Id. - - The initial request for authentication and/or authorization of a user - would include the Session-Id AVP. The Session-Id is then used in all - subsequent messages to identify the user's session (see Section 8 for - - - -Fajardo, et al. Standards Track [Page 20] - -RFC 6733 Diameter Base Protocol October 2012 - - - more information). The communicating party may accept the request or - reject it by returning an answer message with the Result-Code AVP set - to indicate that an error occurred. The specific behavior of the - Diameter server or client receiving a request depends on the Diameter - application employed. - - Session state (associated with a Session-Id) MUST be freed upon - receipt of the Session-Termination-Request, Session-Termination- - Answer, expiration of authorized service time in the Session-Timeout - AVP, and according to rules established in a particular Diameter - application. -</pre> - -<p> -Like Session-Id, session state is maintained by the diameter user: -diameter has no session state of its own and does not interpret -STR/STA in any way.</p> - -<pre> - - The base Diameter protocol may be used by itself for accounting - applications. For authentication and authorization, it is always - extended for a particular application. - - Diameter clients MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement the client's service, e.g., - Network Access Server Requirements (NASREQ) [RFC2881] and/or Mobile - IPv4. A Diameter client MUST be referred to as "Diameter X Client" - where X is the application that it supports and not a "Diameter - Client". - - Diameter servers MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement the intended service, e.g., - NASREQ and/or Mobile IPv4. A Diameter server MUST be referred to as - "Diameter X Server" where X is the application that it supports, and - not a "Diameter Server". - - Diameter relays and redirect agents are transparent to the Diameter - applications, but they MUST support the Diameter base protocol, which - includes accounting, and all Diameter applications. - - Diameter proxies MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement proxied services, e.g., - NASREQ and/or Mobile IPv4. A Diameter proxy MUST be referred to as - "Diameter X Proxy" where X is the application which it supports, and - not a "Diameter Proxy". - -</pre> - -&nada; - -<pre> - - - - - - - - - -Fajardo, et al. Standards Track [Page 21] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.1. Transport - - The Diameter Transport profile is defined in [RFC3539]. - - The base Diameter protocol is run on port 3868 for both TCP [RFC0793] - and SCTP [RFC4960]. For TLS [RFC5246] and Datagram Transport Layer - Security (DTLS) [RFC6347], a Diameter node that initiates a - connection prior to any message exchanges MUST run on port 5658. It - is assumed that TLS is run on top of TCP when it is used, and DTLS is - run on top of SCTP when it is used. -</pre> - -<p> -Which port a transport connects to or listens on is a matter of -configuration. -Both &man_tcp; and &man_sctp; will default to 3868 if no other value -is specified.</p> - -<pre> - - If the Diameter peer does not support receiving TLS/TCP and DTLS/SCTP - connections on port 5658 (i.e., the peer complies only with RFC - 3588), then the initiator MAY revert to using TCP or SCTP on port - 3868. Note that this scheme is kept only for the purpose of backward - compatibility and that there are inherent security vulnerabilities - when the initial CER/CEA messages are sent unprotected (see - Section 5.6). - - Diameter clients MUST support either TCP or SCTP; agents and servers - SHOULD support both. - - A Diameter node MAY initiate connections from a source port other - than the one that it declares it accepts incoming connections on, and - it MUST always be prepared to receive connections on port 3868 for - TCP or SCTP and port 5658 for TLS/TCP and DTLS/SCTP connections. - When DNS-based peer discovery (Section 5.2) is used, the port numbers - received from SRV records take precedence over the default ports - (3868 and 5658). - - A given Diameter instance of the peer state machine MUST NOT use more - than one transport connection to communicate with a given peer, - unless multiple instances exist on the peer, in which, case a - separate connection per process is allowed. -</pre> - -<p> -The &mod_service_opt; <c>restrict_connection</c> controls to what -extent a diameter service allows multiple connections to the same -peer. -(As identified by the value of Origin-Host received from it -during capabilities exchange.)</p> - -<pre> - - When no transport connection exists with a peer, an attempt to - connect SHOULD be made periodically. This behavior is handled via - the Tc timer (see Section 12 for details), whose recommended value is - 30 seconds. There are certain exceptions to this rule, such as when - a peer has terminated the transport connection stating that it does - not wish to communicate. - -</pre> - -<p> -The frequency of reconnection attempts is configured with the -&mod_transport_opt; <c>connect_timer</c> and -<c>watchdog_timer</c>.</p> - -<pre> - - When connecting to a peer and either zero or more transports are - specified, TLS SHOULD be tried first, followed by DTLS, then by TCP, - and finally by SCTP. See Section 5.2 for more information on peer - discovery. -</pre> - -<p> -The order in which different transports are attempted depends on the -order of &mod_transport_opt; <c>transport_module</c> and -<c>transport_config</c> tuples in transport configuration.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 22] - -RFC 6733 Diameter Base Protocol October 2012 - - - Diameter implementations SHOULD be able to interpret ICMP protocol - port unreachable messages as explicit indications that the server is - not reachable, subject to security policy on trusting such messages. - Further guidance regarding the treatment of ICMP errors can be found - in [RFC5927] and [RFC5461]. Diameter implementations SHOULD also be - able to interpret a reset from the transport and timed-out connection - attempts. If Diameter receives data from the lower layer that cannot - be parsed or identified as a Diameter error made by the peer, the - stream is compromised and cannot be recovered. The transport - connection MUST be closed using a RESET call (send a TCP RST bit) or - an SCTP ABORT message (graceful closure is compromised). -</pre> - -<p> -ICMP messages and other transport-level errors aren't directly -visible to diameter but transport implementations like &man_tcp; and -&man_sctp; propagate these as terminating transport processes.</p> - -<pre> - -2.1.1. SCTP Guidelines - - Diameter messages SHOULD be mapped into SCTP streams in a way that - avoids head-of-the-line (HOL) blocking. Among different ways of - performing the mapping that fulfill this requirement it is - RECOMMENDED that a Diameter node send every Diameter message (request - or response) over stream zero with the unordered flag set. However, - Diameter nodes MAY select and implement other design alternatives for - avoiding HOL blocking such as using multiple streams with the - unordered flag cleared (as originally instructed in RFC 3588). On - the receiving side, a Diameter entity MUST be ready to receive - Diameter messages over any stream, and it is free to return responses - over a different stream. This way, both sides manage the available - streams in the sending direction, independently of the streams chosen - by the other side to send a particular Diameter message. These - messages can be out-of-order and belong to different Diameter - sessions. -</pre> - -<p> -&man_sctp; allows the sender to specify a stream number explicitly. -The stream on which an incoming message is received it passed to -&app_handle_request; and &app_handle_answer; callbacks as -<c>transport_data</c> in a <c>#diameter_packet{}</c>.</p> - -<p> -Ordered or unordered delivery can be configured per transport.</p> - -<pre> - - Out-of-order delivery has special concerns during a connection - establishment and termination. When a connection is established, the - responder side sends a CEA message and moves to R-Open state as - specified in Section 5.6. If an application message is sent shortly - after the CEA and delivered out-of-order, the initiator side, still - in Wait-I-CEA state, will discard the application message and close - the connection. In order to avoid this race condition, the receiver - side SHOULD NOT use out-of-order delivery methods until the first - message has been received from the initiator, proving that it has - moved to I-Open state. To trigger such a message, the receiver side - could send a DWR immediately after sending a CEA. Upon reception of - the corresponding DWA, the receiver side should start using out-of- - order delivery methods to counter the HOL blocking. -</pre> - -<p> -&man_sctp; does not currently allow the user to switch between ordered -and unordered delivery, or to specify the manner of sending per -message: one or the other must be configured, the defaults being -ordered.</p> - -<pre> - - Another race condition may occur when DPR and DPA messages are used. - Both DPR and DPA are small in size; thus, they may be delivered to - the peer faster than application messages when an out-of-order - delivery mechanism is used. Therefore, it is possible that a DPR/DPA - - - -Fajardo, et al. Standards Track [Page 23] - -RFC 6733 Diameter Base Protocol October 2012 - - - exchange completes while application messages are still in transit, - resulting in a loss of these messages. An implementation could - mitigate this race condition, for example, using timers, and wait for - a short period of time for pending application level messages to - arrive before proceeding to disconnect the transport connection. - Eventually, lost messages are handled by the retransmission mechanism - described in Section 5.5.4. - - A Diameter agent SHOULD use dedicated payload protocol identifiers - (PPIDs) for clear text and encrypted SCTP DATA chunks instead of only - using the unspecified payload protocol identifier (value 0). For - this purpose, two PPID values are allocated: the PPID value 46 is for - Diameter messages in clear text SCTP DATA chunks, and the PPID value - 47 is for Diameter messages in protected DTLS/SCTP DATA chunks. -</pre> - -&nada; - -<pre> - -2.2. Securing Diameter Messages - - Connections between Diameter peers SHOULD be protected by TLS/TCP and - DTLS/SCTP. All Diameter base protocol implementations MUST support - the use of TLS/TCP and DTLS/SCTP. If desired, alternative security - mechanisms that are independent of Diameter, such as IPsec [RFC4301], - can be deployed to secure connections between peers. The Diameter - protocol MUST NOT be used without one of TLS, DTLS, or IPsec. -</pre> - -<p> -As noted above, DTLS is not currently supported and IPsec usage is -transparent to diameter. -Security is not enforced by diameter.</p> - -<pre> - -2.3. Diameter Application Compliance - - Application Ids are advertised during the capabilities exchange phase - (see Section 5.3). Advertising support of an application implies - that the sender supports the functionality specified in the - respective Diameter application specification. - - Implementations MAY add arbitrary optional AVPs with the M-bit - cleared (including vendor-specific AVPs) to a command defined in an - application, but only if the command's CCF syntax specification - allows for it. Please refer to Section 11.1.1 for details. -</pre> - -&nada; - -<pre> - -2.4. Application Identifiers - - Each Diameter application MUST have an IANA-assigned Application ID. - The base protocol does not require an Application Id since its - support is mandatory. During the capabilities exchange, Diameter - nodes inform their peers of locally supported applications. - Furthermore, all Diameter messages contain an Application Id, which - is used in the message forwarding process. - - - - - - - -Fajardo, et al. Standards Track [Page 24] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following Application Id values are defined: - - Diameter common message 0 - Diameter base accounting 3 - Relay 0xffffffff -</pre> - -<p> -These applications are implemented in the dictionary modules -<c>diameter_gen_base_rfc6733</c>, <c>diameter_gen_acct_rfc6733</c> and -<c>diameter_relay</c> respectively. -There are also RFC 3588 versions or the common and accounting -dictionaries: <c>diameter_gen_base_rfc3588</c> and -<c>diameter_base_accounting</c>. -(The inconsistent naming is historical.) -Dictionary modules are configured using the &mod_application_opt; -<c>dictionary</c>.</p> - -<pre> - Relay and redirect agents MUST advertise the Relay Application ID, - while all other Diameter nodes MUST advertise locally supported - applications. The receiver of a Capabilities Exchange message - advertising relay service MUST assume that the sender supports all - current and future applications. - - Diameter relay and proxy agents are responsible for finding an - upstream server that supports the application of a particular - message. If none can be found, an error message is returned with the - Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. -</pre> - -&nada; - -<pre> - -2.5. Connections vs. Sessions - - This section attempts to provide the reader with an understanding of - the difference between "connection" and "session", which are terms - used extensively throughout this document. - - A connection refers to a transport-level connection between two peers - that is used to send and receive Diameter messages. A session is a - logical concept at the application layer that exists between the - Diameter client and the Diameter server; it is identified via the - Session-Id AVP. - - +--------+ +-------+ +--------+ - | Client | | Relay | | Server | - +--------+ +-------+ +--------+ - <----------> <----------> - peer connection A peer connection B - - <-----------------------------> - User session x - - Figure 1: Diameter Connections and Sessions - - In the example provided in Figure 1, peer connection A is established - between the client and the relay. Peer connection B is established - between the relay and the server. User session X spans from the - client via the relay to the server. Each "user" of a service causes - an auth request to be sent, with a unique session identifier. Once - accepted by the server, both the client and the server are aware of - the session. - - - - -Fajardo, et al. Standards Track [Page 25] - -RFC 6733 Diameter Base Protocol October 2012 - - - It is important to note that there is no relationship between a - connection and a session, and that Diameter messages for multiple - sessions are all multiplexed through a single connection. Also, note - that Diameter messages pertaining to the session, both application- - specific and those that are defined in this document such as ASR/ASA, - RAR/RAA, and STR/STA, MUST carry the Application Id of the - application. Diameter messages pertaining to peer connection - establishment and maintenance such as CER/CEA, DWR/DWA, and DPR/DPA - MUST carry an Application Id of zero (0). -</pre> - -<p> -As noted above, diameter is not involved in session management. -This is the responsibility of the diameter user.</p> - -<pre> - -2.6. Peer Table - - The Diameter peer table is used in message forwarding and is - referenced by the routing table. A peer table entry contains the - following fields: - - Host Identity - - Following the conventions described for the DiameterIdentity- - derived AVP data format in Section 4.3.1, this field contains the - contents of the Origin-Host (Section 6.3) AVP found in the CER or - CEA message. - - StatusT - - This is the state of the peer entry, and it MUST match one of the - values listed in Section 5.6. - - Static or Dynamic - - Specifies whether a peer entry was statically configured or - dynamically discovered. - - Expiration Time - - Specifies the time at which dynamically discovered peer table - entries are to be either refreshed or expired. If public key - certificates are used for Diameter security (e.g., with TLS), this - value MUST NOT be greater than the expiry times in the relevant - certificates. - - TLS/TCP and DTLS/SCTP Enabled - - Specifies whether TLS/TCP and DTLS/SCTP is to be used when - communicating with the peer. - - Additional security information, when needed (e.g., keys, - certificates). -</pre> - -<p> -The Peer Table is not directly accessible to the diameter user. -Information about connected peers can be retrieved using -&mod_service_info;.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 26] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.7. Routing Table - - All Realm-Based routing lookups are performed against what is - commonly known as the routing table (see Section 12). Each routing - table entry contains the following fields: - - Realm Name - - This is the field that MUST be used as a primary key in the - routing table lookups. Note that some implementations perform - their lookups based on longest-match-from-the-right on the realm - rather than requiring an exact match. - - Application Identifier - - An application is identified by an Application Id. A route entry - can have a different destination based on the Application Id in - the message header. This field MUST be used as a secondary key - field in routing table lookups. - - Local Action - - The Local Action field is used to identify how a message should be - treated. The following actions are supported: - - 1. LOCAL - Diameter messages that can be satisfied locally and do - not need to be routed to another Diameter entity. - - 2. RELAY - All Diameter messages that fall within this category - MUST be routed to a next-hop Diameter entity that is indicated - by the identifier described below. Routing is done without - modifying any non-routing AVPs. See Section 6.1.9 for - relaying guidelines. - - 3. PROXY - All Diameter messages that fall within this category - MUST be routed to a next Diameter entity that is indicated by - the identifier described below. The local server MAY apply - its local policies to the message by including new AVPs to the - message prior to routing. See Section 6.1.9 for proxying - guidelines. - - 4. REDIRECT - Diameter messages that fall within this category - MUST have the identity of the home Diameter server(s) - appended, and returned to the sender of the message. See - Section 6.1.8 for redirection guidelines. - - - - - - -Fajardo, et al. Standards Track [Page 27] - -RFC 6733 Diameter Base Protocol October 2012 - - - Server Identifier - - The identity of one or more servers to which the message is to be - routed. This identity MUST also be present in the Host Identity - field of the peer table (Section 2.6). When the Local Action is - set to RELAY or PROXY, this field contains the identity of the - server(s) to which the message MUST be routed. When the Local - Action field is set to REDIRECT, this field contains the identity - of one or more servers to which the message MUST be redirected. - - Static or Dynamic - - Specifies whether a route entry was statically configured or - dynamically discovered. - - Expiration Time - - Specifies the time at which a dynamically discovered route table - entry expires. If public key certificates are used for Diameter - security (e.g., with TLS), this value MUST NOT be greater than the - expiry time in the relevant certificates. - - It is important to note that Diameter agents MUST support at least - one of the LOCAL, RELAY, PROXY, or REDIRECT modes of operation. - Agents do not need to support all modes of operation in order to - conform with the protocol specification, but they MUST follow the - protocol compliance guidelines in Section 2. Relay agents and - proxies MUST NOT reorder AVPs. - - The routing table MAY include a default entry that MUST be used for - any requests not matching any of the other entries. The routing - table MAY consist of only such an entry. - - When a request is routed, the target server MUST have advertised the - Application Id (see Section 2.4) for the given message or have - advertised itself as a relay or proxy agent. Otherwise, an error is - returned with the Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. -</pre> - -<p> -Routing does not need specific support in diameter: a user can -maintain their own routing table if desired and implement any desired -routing in &man_app; callbacks. -However, it may be convenient to add more specific routing support to -diameter in the future.</p> - -<pre> - -2.8. Role of Diameter Agents - - In addition to clients and servers, the Diameter protocol introduces - relay, proxy, redirect, and translation agents, each of which is - defined in Section 1.2. Diameter agents are useful for several - reasons: -</pre> - -<p> -An noted above, the role a node plays is largely a question of -configuration and &man_app; callback implementation.</p> - -<pre> - - o They can distribute administration of systems to a configurable - grouping, including the maintenance of security associations. - - - - -Fajardo, et al. Standards Track [Page 28] - -RFC 6733 Diameter Base Protocol October 2012 - - - o They can be used for concentration of requests from a number of - co-located or distributed NAS equipment sets to a set of like user - groups. - - o They can do value-added processing to the requests or responses. - - o They can be used for load balancing. - - o A complex network will have multiple authentication sources, they - can sort requests and forward towards the correct target. - - The Diameter protocol requires that agents maintain transaction - state, which is used for failover purposes. Transaction state - implies that upon forwarding a request, its Hop-by-Hop Identifier is - saved; the field is replaced with a locally unique identifier, which - is restored to its original value when the corresponding answer is - received. The request's state is released upon receipt of the - answer. A stateless agent is one that only maintains transaction - state. - - The Proxy-Info AVP allows stateless agents to add local state to a - Diameter request, with the guarantee that the same state will be - present in the answer. However, the protocol's failover procedures - require that agents maintain a copy of pending requests. - - A stateful agent is one that maintains session state information by - keeping track of all authorized active sessions. Each authorized - session is bound to a particular service, and its state is considered - active until either the agent is notified otherwise or the session - expires. Each authorized session has an expiration, which is - communicated by Diameter servers via the Session-Timeout AVP. - - Maintaining session state may be useful in certain applications, such - as: - - o Protocol translation (e.g., RADIUS <-> Diameter) - - o Limiting resources authorized to a particular user - - o Per-user or per-transaction auditing - - A Diameter agent MAY act in a stateful manner for some requests and - be stateless for others. A Diameter implementation MAY act as one - type of agent for some requests and as another type of agent for - others. -</pre> - -&nada; - -<pre> - - - - - - -Fajardo, et al. Standards Track [Page 29] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.8.1. Relay Agents - - Relay agents are Diameter agents that accept requests and route - messages to other Diameter nodes based on information found in the - messages (e.g., the value of the Destination-Realm AVP Section 6.6). - This routing decision is performed using a list of supported realms - and known peers. This is known as the routing table, as is defined - further in Section 2.7. - - Relays may, for example, be used to aggregate requests from multiple - Network Access Servers (NASes) within a common geographical area - (Point of Presence, POP). The use of relays is advantageous since it - eliminates the need for NASes to be configured with the necessary - security information they would otherwise require to communicate with - Diameter servers in other realms. Likewise, this reduces the - configuration load on Diameter servers that would otherwise be - necessary when NASes are added, changed, or deleted. - - Relays modify Diameter messages by inserting and removing routing - information, but they do not modify any other portion of a message. - Relays SHOULD NOT maintain session state but MUST maintain - transaction state. - - +------+ ---------> +------+ ---------> +------+ - | | 1. Request | | 2. Request | | - | NAS | | DRL | | HMS | - | | 4. Answer | | 3. Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 2: Relaying of Diameter messages - - The example provided in Figure 2 depicts a request issued from a NAS, - which is an access device, for the user [email protected]. Prior to - issuing the request, the NAS performs a Diameter route lookup, using - "example.com" as the key, and determines that the message is to be - relayed to a DRL, which is a Diameter relay. The DRL performs the - same route lookup as the NAS, and relays the message to the HMS, - which is example.com's home server. The HMS identifies that the - request can be locally supported (via the realm), processes the - authentication and/or authorization request, and replies with an - answer, which is routed back to the NAS using saved transaction - state. - - Since relays do not perform any application-level processing, they - provide relaying services for all Diameter applications; therefore, - they MUST advertise the Relay Application Id. -</pre> - -<p> -Requests are relayed by returning a <c>relay</c> tuple from a -&app_handle_request; callback.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 30] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.8.2. Proxy Agents - - Similar to relays, proxy agents route Diameter messages using the - Diameter routing table. However, they differ since they modify - messages to implement policy enforcement. This requires that proxies - maintain the state of their downstream peers (e.g., access devices) - to enforce resource usage, provide admission control, and provide - provisioning. - - Proxies may, for example, be used in call control centers or access - ISPs that provide outsourced connections; they can monitor the number - and type of ports in use and make allocation and admission decisions - according to their configuration. - - Since enforcing policies requires an understanding of the service - being provided, proxies MUST only advertise the Diameter applications - they support. -</pre> - -&nada; - -<pre> - -2.8.3. Redirect Agents - - Redirect agents are useful in scenarios where the Diameter routing - configuration needs to be centralized. An example is a redirect - agent that provides services to all members of a consortium, but does - not wish to be burdened with relaying all messages between realms. - This scenario is advantageous since it does not require that the - consortium provide routing updates to its members when changes are - made to a member's infrastructure. - - Since redirect agents do not relay messages, and only return an - answer with the information necessary for Diameter agents to - communicate directly, they do not modify messages. Since redirect - agents do not receive answer messages, they cannot maintain session - state. - - The example provided in Figure 3 depicts a request issued from the - access device, NAS, for the user [email protected]. The message is - forwarded by the NAS to its relay, DRL, which does not have a routing - entry in its Diameter routing table for example.com. The DRL has a - default route configured to DRD, which is a redirect agent that - returns a redirect notification to DRL, as well as the HMS' contact - information. Upon receipt of the redirect notification, the DRL - establishes a transport connection with the HMS, if one doesn't - already exist, and forwards the request to it. - - - - - - - - -Fajardo, et al. Standards Track [Page 31] - -RFC 6733 Diameter Base Protocol October 2012 - - - +------+ - | | - | DRD | - | | - +------+ - ^ | - 2. Request | | 3. Redirection - | | Notification - | v - +------+ ---------> +------+ ---------> +------+ - | | 1. Request | | 4. Request | | - | NAS | | DRL | | HMS | - | | 6. Answer | | 5. Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 3: Redirecting a Diameter Message - - Since redirect agents do not perform any application-level - processing, they provide relaying services for all Diameter - applications; therefore, they MUST advertise the Relay Application - ID. -</pre> - -&nada; - -<pre> - -2.8.4. Translation Agents - - A translation agent is a device that provides translation between two - protocols (e.g., RADIUS<->Diameter, TACACS+<->Diameter). Translation - agents are likely to be used as aggregation servers to communicate - with a Diameter infrastructure, while allowing for the embedded - systems to be migrated at a slower pace. - - Given that the Diameter protocol introduces the concept of long-lived - authorized sessions, translation agents MUST be session stateful and - MUST maintain transaction state. - - Translation of messages can only occur if the agent recognizes the - application of a particular request; therefore, translation agents - MUST only advertise their locally supported applications. - - +------+ ---------> +------+ ---------> +------+ - | | RADIUS Request | | Diameter Request | | - | NAS | | TLA | | HMS | - | | RADIUS Answer | | Diameter Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 4: Translation of RADIUS to Diameter -</pre> - -&nada; - -<pre> - - - - -Fajardo, et al. Standards Track [Page 32] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.9. Diameter Path Authorization - - As noted in Section 2.2, Diameter provides transmission-level - security for each connection using TLS/TCP and DTLS/SCTP. Therefore, - each connection can be authenticated and can be replay and integrity - protected. - - In addition to authenticating each connection, the entire session - MUST also be authorized. Before initiating a connection, a Diameter - peer MUST check that its peers are authorized to act in their roles. - For example, a Diameter peer may be authentic, but that does not mean - that it is authorized to act as a Diameter server advertising a set - of Diameter applications. - - Prior to bringing up a connection, authorization checks are performed - at each connection along the path. Diameter capabilities negotiation - (CER/CEA) also MUST be carried out, in order to determine what - Diameter applications are supported by each peer. Diameter sessions - MUST be routed only through authorized nodes that have advertised - support for the Diameter application required by the session. - - As noted in Section 6.1.9, a relay or proxy agent MUST append a - Route-Record AVP to all requests forwarded. The AVP contains the - identity of the peer from which the request was received. - - The home Diameter server, prior to authorizing a session, MUST check - the Route-Record AVPs to make sure that the route traversed by the - request is acceptable. For example, administrators within the home - realm may not wish to honor requests that have been routed through an - untrusted realm. By authorizing a request, the home Diameter server - is implicitly indicating its willingness to engage in the business - transaction as specified by any contractual relationship between the - server and the previous hop. A DIAMETER_AUTHORIZATION_REJECTED error - message (see Section 7.1.5) is sent if the route traversed by the - request is unacceptable. - - A home realm may also wish to check that each accounting request - message corresponds to a Diameter response authorizing the session. - Accounting requests without corresponding authorization responses - SHOULD be subjected to further scrutiny, as should accounting - requests indicating a difference between the requested and provided - service. - - Forwarding of an authorization response is considered evidence of a - willingness to take on financial risk relative to the session. A - local realm may wish to limit this exposure, for example, by - establishing credit limits for intermediate realms and refusing to - accept responses that would violate those limits. By issuing an - - - -Fajardo, et al. Standards Track [Page 33] - -RFC 6733 Diameter Base Protocol October 2012 - - - accounting request corresponding to the authorization response, the - local realm implicitly indicates its agreement to provide the service - indicated in the authorization response. If the service cannot be - provided by the local realm, then a DIAMETER_UNABLE_TO_COMPLY error - message MUST be sent within the accounting request; a Diameter client - receiving an authorization response for a service that it cannot - perform MUST NOT substitute an alternate service and then send - accounting requests for the alternate service instead. -</pre> - -&nada; - -<pre> - -3. Diameter Header - - A summary of the Diameter header format is shown below. The fields - are transmitted in network byte order. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Version | Message Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Command Flags | Command Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Application-ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Hop-by-Hop Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | End-to-End Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | AVPs ... - +-+-+-+-+-+-+-+-+-+-+-+-+- -</pre> - -<p> -The Diameter Header is represented by the <c>diameter_header</c> -record defined in <c>diameter.hrl</c>. -The <c>diameter_packet</c> record contains a <c>header</c> field whose -value will be a decoded <c>#diameter_header{}</c> for incoming -messages passed to &app_handle_request; and &app_handle_answer; -callbacks. -In the case of outgoing messages, diameter and the relevant -dictionary populate the Diameter Header appropriately, although -&app_prepare_request; and &app_handle_request; callbacks can modify -header values. -(Which can be useful in test.)</p> - -<pre> - - Version - - This Version field MUST be set to 1 to indicate Diameter Version - 1. - - Message Length - - The Message Length field is three octets and indicates the length - of the Diameter message including the header fields and the padded - AVPs. Thus, the Message Length field is always a multiple of 4. - - Command Flags - - The Command Flags field is eight bits. The following bits are - assigned: - - - - - - -Fajardo, et al. Standards Track [Page 34] - -RFC 6733 Diameter Base Protocol October 2012 - - - 0 1 2 3 4 5 6 7 - +-+-+-+-+-+-+-+-+ - |R P E T r r r r| - +-+-+-+-+-+-+-+-+ - - R(equest) - - If set, the message is a request. If cleared, the message is - an answer. - - P(roxiable) - - If set, the message MAY be proxied, relayed, or redirected. If - cleared, the message MUST be locally processed. - - E(rror) - - If set, the message contains a protocol error, and the message - will not conform to the CCF described for this command. - Messages with the 'E' bit set are commonly referred to as error - messages. This bit MUST NOT be set in request messages (see - Section 7.2). - - T(Potentially retransmitted message) - - This flag is set after a link failover procedure, to aid the - removal of duplicate requests. It is set when resending - requests not yet acknowledged, as an indication of a possible - duplicate due to a link failure. This bit MUST be cleared when - sending a request for the first time; otherwise, the sender - MUST set this flag. Diameter agents only need to be concerned - about the number of requests they send based on a single - received request; retransmissions by other entities need not be - tracked. Diameter agents that receive a request with the T - flag set, MUST keep the T flag set in the forwarded request. - This flag MUST NOT be set if an error answer message (e.g., a - protocol error) has been received for the earlier message. It - can be set only in cases where no answer has been received from - the server for a request, and the request has been sent again. - This flag MUST NOT be set in answer messages. - - r(eserved) - - These flag bits are reserved for future use; they MUST be set - to zero and ignored by the receiver. -</pre> - -<p> -Reserved bits are set to 0 in outgoing messages.</p> - -<pre> - - - - - - -Fajardo, et al. Standards Track [Page 35] - -RFC 6733 Diameter Base Protocol October 2012 - - - Command Code - - The Command Code field is three octets and is used in order to - communicate the command associated with the message. The 24-bit - address space is managed by IANA (see Section 3.1). Command Code - values 16,777,214 and 16,777,215 (hexadecimal values FFFFFE- - FFFFFF) are reserved for experimental use (see Section 11.2). - - Application-ID - - Application-ID is four octets and is used to identify for which - application the message is applicable. The application can be an - authentication application, an accounting application, or a - vendor-specific application. - - The value of the Application-ID field in the header MUST be the - same as any relevant Application-Id AVPs contained in the message. - - Hop-by-Hop Identifier - - The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in - network byte order) that aids in matching requests and replies. - The sender MUST ensure that the Hop-by-Hop Identifier in a request - is unique on a given connection at any given time, and it MAY - attempt to ensure that the number is unique across reboots. The - sender of an answer message MUST ensure that the Hop-by-Hop - Identifier field contains the same value that was found in the - corresponding request. The Hop-by-Hop Identifier is normally a - monotonically increasing number, whose start value was randomly - generated. An answer message that is received with an unknown - Hop-by-Hop Identifier MUST be discarded. - - End-to-End Identifier - - The End-to-End Identifier is an unsigned 32-bit integer field (in - network byte order) that is used to detect duplicate messages. - Upon reboot, implementations MAY set the high order 12 bits to - contain the low order 12 bits of current time, and the low order - 20 bits to a random value. Senders of request messages MUST - insert a unique identifier on each message. The identifier MUST - remain locally unique for a period of at least 4 minutes, even - across reboots. The originator of an answer message MUST ensure - that the End-to-End Identifier field contains the same value that - was found in the corresponding request. The End-to-End Identifier - MUST NOT be modified by Diameter agents of any kind. The - combination of the Origin-Host AVP (Section 6.3) and this field is - used to detect duplicates. Duplicate requests SHOULD cause the - same answer to be transmitted (modulo the Hop-by-Hop Identifier - - - -Fajardo, et al. Standards Track [Page 36] - -RFC 6733 Diameter Base Protocol October 2012 - - - field and any routing AVPs that may be present), and they MUST NOT - affect any state that was set when the original request was - processed. Duplicate answer messages that are to be locally - consumed (see Section 6.2) SHOULD be silently discarded. - - AVPs - - AVPs are a method of encapsulating information relevant to the - Diameter message. See Section 4 for more information on AVPs. -</pre> - -&nada; - -<pre> - -3.1. Command Codes - - Each command Request/Answer pair is assigned a Command Code, and the - sub-type (i.e., request or answer) is identified via the 'R' bit in - the Command Flags field of the Diameter header. - - Every Diameter message MUST contain a Command Code in its header's - Command Code field, which is used to determine the action that is to - be taken for a particular message. The following Command Codes are - defined in the Diameter base protocol: - - Section - Command Name Abbrev. Code Reference - -------------------------------------------------------- - Abort-Session-Request ASR 274 8.5.1 - Abort-Session-Answer ASA 274 8.5.2 - Accounting-Request ACR 271 9.7.1 - Accounting-Answer ACA 271 9.7.2 - Capabilities-Exchange- CER 257 5.3.1 - Request - Capabilities-Exchange- CEA 257 5.3.2 - Answer - Device-Watchdog-Request DWR 280 5.5.1 - Device-Watchdog-Answer DWA 280 5.5.2 - Disconnect-Peer-Request DPR 282 5.4.1 - Disconnect-Peer-Answer DPA 282 5.4.2 - Re-Auth-Request RAR 258 8.3.1 - Re-Auth-Answer RAA 258 8.3.2 - Session-Termination- STR 275 8.4.1 - Request - Session-Termination- STA 275 8.4.2 - Answer -</pre> - -<p> -These messages are all defined in diameter's implementation of the -common dictionary in modules <c>diameter_gen_base_rfc6733</c> and -<c>diameter_gen_base_rfc3588</c>. -Corresponding record definitions are found in -<c>diameter_gen_base_rfc6733.hrl</c> and -<c>diameter_gen_base_rfc3588.hrl</c>.</p> - -<pre> - - - - - - - - - -Fajardo, et al. Standards Track [Page 37] - -RFC 6733 Diameter Base Protocol October 2012 - - -3.2. Command Code Format Specification - - Every Command Code defined MUST include a corresponding Command Code - Format (CCF) specification, which is used to define the AVPs that - MUST or MAY be present when sending the message. The following ABNF - specifies the CCF used in the definition: -</pre> - -<p> -The CCF is what is specified in the <c>@messages</c> section of the -&man_dict; format, except as noted below.</p> - -<pre> - - command-def = "<" command-name ">" "::=" diameter-message -</pre> - -<p> -Angle brackets are currently not allowed here. -This was a change between RFC 3588 and RFC 6733: the former disallowed -them in the grammar but included them in its own command definitions.</p> - -<pre> - - command-name = diameter-name - - diameter-name = ALPHA *(ALPHA / DIGIT / "-") - - diameter-message = header *fixed *required *optional - - header = "<Diameter-Header:" command-id - [r-bit] [p-bit] [e-bit] [application-id]">" - - application-id = 1*DIGIT - - command-id = 1*DIGIT - ; The Command Code assigned to the command. - - r-bit = ", REQ" - ; If present, the 'R' bit in the Command - ; Flags is set, indicating that the message - ; is a request as opposed to an answer. - - p-bit = ", PXY" - ; If present, the 'P' bit in the Command - ; Flags is set, indicating that the message - ; is proxiable. - - e-bit = ", ERR" - ; If present, the 'E' bit in the Command - ; Flags is set, indicating that the answer - ; message contains a Result-Code AVP in - ; the "protocol error" class. - - fixed = [qual] "<" avp-spec ">" - ; Defines the fixed position of an AVP. - - required = [qual] "{" avp-spec "}" - ; The AVP MUST be present and can appear - ; anywhere in the message. - - - - - - -Fajardo, et al. Standards Track [Page 38] - -RFC 6733 Diameter Base Protocol October 2012 - - - optional = [qual] "[" avp-name "]" - ; The avp-name in the 'optional' rule cannot - ; evaluate to any AVP Name that is included - ; in a fixed or required rule. The AVP can - ; appear anywhere in the message. - ; - ; NOTE: "[" and "]" have a slightly different - ; meaning than in ABNF. These braces - ; cannot be used to express optional fixed rules - ; (such as an optional ICV at the end). To do - ; this, the convention is '0*1fixed'. - - qual = [min] "*" [max] - ; See ABNF conventions, RFC 5234, Section 4. - ; The absence of any qualifier depends on - ; whether it precedes a fixed, required, or - ; optional rule. If a fixed or required rule has - ; no qualifier, then exactly one such AVP MUST - ; be present. If an optional rule has no - ; qualifier, then 0 or 1 such AVP may be - ; present. If an optional rule has a qualifier, - ; then the value of min MUST be 0 if present. - - min = 1*DIGIT - ; The minimum number of times the element may - ; be present. If absent, the default value is 0 - ; for fixed and optional rules and 1 for - ; required rules. The value MUST be at least 1 - ; for required rules. - - max = 1*DIGIT - ; The maximum number of times the element may - ; be present. If absent, the default value is - ; infinity. A value of 0 implies the AVP MUST - ; NOT be present. - - avp-spec = diameter-name - ; The avp-spec has to be an AVP Name, defined - ; in the base or extended Diameter - ; specifications. - - avp-name = avp-spec / "AVP" - ; The string "AVP" stands for *any* arbitrary AVP - ; Name, not otherwise listed in that Command Code - ; definition. The inclusion of this string - ; is recommended for all CCFs to allow for - ; extensibility. - - - - -Fajardo, et al. Standards Track [Page 39] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following is a definition of a fictitious Command Code: - - Example-Request ::= < Diameter Header: 9999999, REQ, PXY > - { User-Name } - 1* { Origin-Host } - * [ AVP ] -</pre> - -&nada; - -<pre> - -3.3. Diameter Command Naming Conventions - - Diameter command names typically includes one or more English words - followed by the verb "Request" or "Answer". Each English word is - delimited by a hyphen. A three-letter acronym for both the request - and answer is also normally provided. - - An example is a message set used to terminate a session. The command - name is Session-Terminate-Request and Session-Terminate-Answer, while - the acronyms are STR and STA, respectively. - - Both the request and the answer for a given command share the same - Command Code. The request is identified by the R(equest) bit in the - Diameter header set to one (1), to ask that a particular action be - performed, such as authorizing a user or terminating a session. Once - the receiver has completed the request, it issues the corresponding - answer, which includes a result code that communicates one of the - following: - - o The request was successful - - o The request failed - - o An additional request has to be sent to provide information the - peer requires prior to returning a successful or failed answer. - - o The receiver could not process the request, but provides - information about a Diameter peer that is able to satisfy the - request, known as redirect. - - Additional information, encoded within AVPs, may also be included in - answer messages. -</pre> - -<p> -The &man_dict; format places no requirement on the naming of commands.</p> - -<pre> - -4. Diameter AVPs - - Diameter AVPs carry specific authentication, accounting, - authorization, and routing information as well as configuration - details for the request and reply. - - - - - - -Fajardo, et al. Standards Track [Page 40] - -RFC 6733 Diameter Base Protocol October 2012 - - - Each AVP of type OctetString MUST be padded to align on a 32-bit - boundary, while other AVP types align naturally. A number of zero- - valued bytes are added to the end of the AVP Data field until a word - boundary is reached. The length of the padding is not reflected in - the AVP Length field. - -4.1. AVP Header - - The fields in the AVP header MUST be sent in network byte order. The - format of the header is: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | AVP Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |V M P r r r r r| AVP Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vendor-ID (opt) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Data ... - +-+-+-+-+-+-+-+-+ - - AVP Code - - The AVP Code, combined with the Vendor-Id field, identifies the - attribute uniquely. AVP numbers 1 through 255 are reserved for - reuse of RADIUS attributes, without setting the Vendor-Id field. - AVP numbers 256 and above are used for Diameter, which are - allocated by IANA (see Section 11.1.1). - - AVP Flags - - The AVP Flags field informs the receiver how each attribute must - be handled. New Diameter applications SHOULD NOT define - additional AVP Flag bits. However, note that new Diameter - applications MAY define additional bits within the AVP header, and - an unrecognized bit SHOULD be considered an error. The sender of - the AVP MUST set 'R' (reserved) bits to 0 and the receiver SHOULD - ignore all 'R' (reserved) bits. The 'P' bit has been reserved for - future usage of end-to-end security. At the time of writing, - there are no end-to-end security mechanisms specified; therefore, - the 'P' bit SHOULD be set to 0. - - The 'M' bit, known as the Mandatory bit, indicates whether the - receiver of the AVP MUST parse and understand the semantics of the - AVP including its content. The receiving entity MUST return an - appropriate error message if it receives an AVP that has the M-bit - - - -Fajardo, et al. Standards Track [Page 41] - -RFC 6733 Diameter Base Protocol October 2012 - - - set but does not understand it. An exception applies when the AVP - is embedded within a Grouped AVP. See Section 4.4 for details. - Diameter relay and redirect agents MUST NOT reject messages with - unrecognized AVPs. - - The 'M' bit MUST be set according to the rules defined in the - application specification that introduces or reuses this AVP. - Within a given application, the M-bit setting for an AVP is - defined either for all command types or for each command type. - - AVPs with the 'M' bit cleared are informational only; a receiver - that receives a message with such an AVP that is not supported, or - whose value is not supported, MAY simply ignore the AVP. - - The 'V' bit, known as the Vendor-Specific bit, indicates whether - the optional Vendor-ID field is present in the AVP header. When - set, the AVP Code belongs to the specific vendor code address - space. - - AVP Length - - The AVP Length field is three octets, and indicates the number of - octets in this AVP including the AVP Code field, AVP Length field, - AVP Flags field, Vendor-ID field (if present), and the AVP Data - field. If a message is received with an invalid attribute length, - the message MUST be rejected. - -4.1.1. Optional Header Elements - - The AVP header contains one optional field. This field is only - present if the respective bit-flag is enabled. - - Vendor-ID - - The Vendor-ID field is present if the 'V' bit is set in the AVP - Flags field. The optional four-octet Vendor-ID field contains the - IANA-assigned "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value, encoded in network byte order. Any vendors or - standardization organizations that are also treated like vendors - in the IANA-managed "SMI Network Management Private Enterprise - Codes" space wishing to implement a vendor-specific Diameter AVP - MUST use their own Vendor-ID along with their privately managed - AVP address space, guaranteeing that they will not collide with - any other vendor's vendor-specific AVP(s) or with future IETF - AVPs. - - - - - - -Fajardo, et al. Standards Track [Page 42] - -RFC 6733 Diameter Base Protocol October 2012 - - - A Vendor-ID value of zero (0) corresponds to the IETF-adopted AVP - values, as managed by IANA. Since the absence of the Vendor-ID - field implies that the AVP in question is not vendor specific, - implementations MUST NOT use the value of zero (0) for the - Vendor-ID field. - -4.2. Basic AVP Data Formats - - The Data field is zero or more octets and contains information - specific to the Attribute. The format and length of the Data field - is determined by the AVP Code and AVP Length fields. The format of - the Data field MUST be one of the following base data types or a data - type derived from the base data types. In the event that a new Basic - AVP Data Format is needed, a new version of this RFC MUST be created. - - OctetString - - The data contains arbitrary data of variable length. Unless - otherwise noted, the AVP Length field MUST be set to at least 8 - (12 if the 'V' bit is enabled). AVP values of this type that are - not a multiple of 4 octets in length are followed by the necessary - padding so that the next AVP (if any) will start on a 32-bit - boundary. - - Integer32 - - 32-bit signed value, in network byte order. The AVP Length field - MUST be set to 12 (16 if the 'V' bit is enabled). - - Integer64 - - 64-bit signed value, in network byte order. The AVP Length field - MUST be set to 16 (20 if the 'V' bit is enabled). - - Unsigned32 - - 32-bit unsigned value, in network byte order. The AVP Length - field MUST be set to 12 (16 if the 'V' bit is enabled). - - Unsigned64 - - 64-bit unsigned value, in network byte order. The AVP Length - field MUST be set to 16 (20 if the 'V' bit is enabled). - - - - - - - - -Fajardo, et al. Standards Track [Page 43] - -RFC 6733 Diameter Base Protocol October 2012 - - - Float32 - - This represents floating point values of single precision as - described by [FLOATPOINT]. The 32-bit value is transmitted in - network byte order. The AVP Length field MUST be set to 12 (16 if - the 'V' bit is enabled). - - Float64 - - This represents floating point values of double precision as - described by [FLOATPOINT]. The 64-bit value is transmitted in - network byte order. The AVP Length field MUST be set to 16 (20 if - the 'V' bit is enabled). - - Grouped - - The Data field is specified as a sequence of AVPs. These AVPs are - concatenated -- including their headers and padding -- in the - order in which they are specified and the result encapsulated in - the Data field. The AVP Length field is set to 8 (12 if the 'V' - bit is enabled) plus the total length of all included AVPs, - including their headers and padding. Thus, the AVP Length field - of an AVP of type Grouped is always a multiple of 4. - -4.3. Derived AVP Data Formats - - In addition to using the Basic AVP Data Formats, applications may - define data formats derived from the Basic AVP Data Formats. An - application that defines new Derived AVP Data Formats MUST include - them in a section titled "Derived AVP Data Formats", using the same - format as the definitions below. Each new definition MUST be either - defined or listed with a reference to the RFC that defines the - format. - -4.3.1. Common Derived AVP Data Formats - - The following are commonly used Derived AVP Data Formats. - - Address - - The Address format is derived from the OctetString Basic AVP - Format. It is a discriminated union representing, for example, a - 32-bit (IPv4) [RFC0791] or 128-bit (IPv6) [RFC4291] address, most - significant octet first. The first two octets of the Address AVP - represent the AddressType, which contains an Address Family, - defined in [IANAADFAM]. The AddressType is used to discriminate - the content and format of the remaining octets. - - - - -Fajardo, et al. Standards Track [Page 44] - -RFC 6733 Diameter Base Protocol October 2012 - - - Time - - The Time format is derived from the OctetString Basic AVP Format. - The string MUST contain four octets, in the same format as the - first four bytes are in the NTP timestamp format. The NTP - timestamp format is defined in Section 3 of [RFC5905]. - - This represents the number of seconds since 0h on 1 January 1900 - with respect to the Coordinated Universal Time (UTC). - - On 6h 28m 16s UTC, 7 February 2036, the time value will overflow. - Simple Network Time Protocol (SNTP) [RFC5905] describes a - procedure to extend the time to 2104. This procedure MUST be - supported by all Diameter nodes. - - UTF8String - - The UTF8String format is derived from the OctetString Basic AVP - Format. This is a human-readable string represented using the - ISO/IEC IS 10646-1 character set, encoded as an OctetString using - the UTF-8 transformation format [RFC3629]. - - Since additional code points are added by amendments to the 10646 - standard from time to time, implementations MUST be prepared to - encounter any code point from 0x00000001 to 0x7fffffff. Byte - sequences that do not correspond to the valid encoding of a code - point into UTF-8 charset or are outside this range are prohibited. - - The use of control codes SHOULD be avoided. When it is necessary - to represent a new line, the control code sequence CR LF SHOULD be - used. - - The use of leading or trailing white space SHOULD be avoided. - - For code points not directly supported by user interface hardware - or software, an alternative means of entry and display, such as - hexadecimal, MAY be provided. - - For information encoded in 7-bit US-ASCII, the UTF-8 charset is - identical to the US-ASCII charset. - - UTF-8 may require multiple bytes to represent a single character / - code point; thus, the length of a UTF8String in octets may be - different from the number of characters encoded. - - Note that the AVP Length field of an UTF8String is measured in - octets not characters. - - - - -Fajardo, et al. Standards Track [Page 45] - -RFC 6733 Diameter Base Protocol October 2012 - - - DiameterIdentity - - The DiameterIdentity format is derived from the OctetString Basic - AVP Format. - - DiameterIdentity = FQDN/Realm - - The DiameterIdentity value is used to uniquely identify either: - - * A Diameter node for purposes of duplicate connection and - routing loop detection. - - * A Realm to determine whether messages can be satisfied locally - or whether they must be routed or redirected. - - When a DiameterIdentity value is used to identify a Diameter node, - the contents of the string MUST be the Fully Qualified Domain Name - (FQDN) of the Diameter node. If multiple Diameter nodes run on - the same host, each Diameter node MUST be assigned a unique - DiameterIdentity. If a Diameter node can be identified by several - FQDNs, a single FQDN should be picked at startup and used as the - only DiameterIdentity for that node, whatever the connection on - which it is sent. In this document, note that DiameterIdentity is - in ASCII form in order to be compatible with existing DNS - infrastructure. See Appendix D for interactions between the - Diameter protocol and Internationalized Domain Names (IDNs). - - DiameterURI - - The DiameterURI MUST follow the Uniform Resource Identifiers (RFC - 3986) syntax [RFC3986] rules specified below: - - "aaa://" FQDN [ port ] [ transport ] [ protocol ] - - ; No transport security - - "aaas://" FQDN [ port ] [ transport ] [ protocol ] - - ; Transport security used - - FQDN = < Fully Qualified Domain Name > - - - - - - - - - - -Fajardo, et al. Standards Track [Page 46] - -RFC 6733 Diameter Base Protocol October 2012 - - - port = ":" 1*DIGIT - - ; One of the ports used to listen for - ; incoming connections. - ; If absent, the default Diameter port - ; (3868) is assumed if no transport - ; security is used and port 5658 when - ; transport security (TLS/TCP and DTLS/SCTP) - ; is used. - - transport = ";transport=" transport-protocol - - ; One of the transports used to listen - ; for incoming connections. If absent, - ; the default protocol is assumed to be TCP. - ; UDP MUST NOT be used when the aaa-protocol - ; field is set to diameter. - - transport-protocol = ( "tcp" / "sctp" / "udp" ) - - protocol = ";protocol=" aaa-protocol - - ; If absent, the default AAA protocol - ; is Diameter. - - aaa-protocol = ( "diameter" / "radius" / "tacacs+" ) - - The following are examples of valid Diameter host identities: - - aaa://host.example.com;transport=tcp - aaa://host.example.com:6666;transport=tcp - aaa://host.example.com;protocol=diameter - aaa://host.example.com:6666;protocol=diameter - aaa://host.example.com:6666;transport=tcp;protocol=diameter - aaa://host.example.com:1813;transport=udp;protocol=radius - - Enumerated - - The Enumerated format is derived from the Integer32 Basic AVP - Format. The definition contains a list of valid values and their - interpretation and is described in the Diameter application - introducing the AVP. - - - - - - - - - -Fajardo, et al. Standards Track [Page 47] - -RFC 6733 Diameter Base Protocol October 2012 - - - IPFilterRule - - The IPFilterRule format is derived from the OctetString Basic AVP - Format and uses the ASCII charset. The rule syntax is a modified - subset of ipfw(8) from FreeBSD. Packets may be filtered based on - the following information that is associated with it: - - Direction (in or out) - Source and destination IP address (possibly masked) - Protocol - Source and destination port (lists or ranges) - TCP flags - IP fragment flag - IP options - ICMP types - - Rules for the appropriate direction are evaluated in order, with the - first matched rule terminating the evaluation. Each packet is - evaluated once. If no rule matches, the packet is dropped if the - last rule evaluated was a permit, and passed if the last rule was a - deny. - - IPFilterRule filters MUST follow the format: - - action dir proto from src to dst [options] - - action permit - Allow packets that match the rule. - deny - Drop packets that match the rule. - - dir "in" is from the terminal, "out" is to the - terminal. - - proto An IP protocol specified by number. The "ip" - keyword means any protocol will match. - - src and dst <address/mask> [ports] - - The <address/mask> may be specified as: - ipno An IPv4 or IPv6 number in dotted- - quad or canonical IPv6 form. Only - this exact IP number will match the - rule. - - - - - - - - - -Fajardo, et al. Standards Track [Page 48] - -RFC 6733 Diameter Base Protocol October 2012 - - - ipno/bits An IP number as above with a mask - width of the form 192.0.2.10/24. In - this case, all IP numbers from - 192.0.2.0 to 192.0.2.255 will match. - The bit width MUST be valid for the - IP version, and the IP number MUST - NOT have bits set beyond the mask. - For a match to occur, the same IP - version must be present in the - packet that was used in describing - the IP address. To test for a - particular IP version, the bits part - can be set to zero. The keyword - "any" is 0.0.0.0/0 or the IPv6 - equivalent. The keyword "assigned" - is the address or set of addresses - assigned to the terminal. For IPv4, - a typical first rule is often "deny - in ip! assigned". - - The sense of the match can be inverted by - preceding an address with the not modifier (!), - causing all other addresses to be matched - instead. This does not affect the selection of - port numbers. - - With the TCP, UDP, and SCTP protocols, optional - ports may be specified as: - - {port/port-port}[,ports[,...]] - - The '-' notation specifies a range of ports - (including boundaries). - - Fragmented packets that have a non-zero offset - (i.e., not the first fragment) will never match - a rule that has one or more port - specifications. See the frag option for - details on matching fragmented packets. - - options: - frag Match if the packet is a fragment and this is not - the first fragment of the datagram. frag may not - be used in conjunction with either tcpflags or - TCP/UDP port specifications. - - - - - - -Fajardo, et al. Standards Track [Page 49] - -RFC 6733 Diameter Base Protocol October 2012 - - - ipoptions spec - Match if the IP header contains the comma-separated - list of options specified in spec. The - supported IP options are: - - ssrr (strict source route), lsrr (loose source - route), rr (record packet route), and ts - (timestamp). The absence of a particular option - may be denoted with a '!'. - - tcpoptions spec - Match if the TCP header contains the comma-separated - list of options specified in spec. The - supported TCP options are: - - mss (maximum segment size), window (tcp window - advertisement), sack (selective ack), ts (rfc1323 - timestamp), and cc (rfc1644 t/tcp connection - count). The absence of a particular option may - be denoted with a '!'. - - established - TCP packets only. Match packets that have the RST - or ACK bits set. - - setup TCP packets only. Match packets that have the SYN - bit set but no ACK bit. - - - tcpflags spec - TCP packets only. Match if the TCP header - contains the comma-separated list of flags - specified in spec. The supported TCP flags are: - - fin, syn, rst, psh, ack, and urg. The absence of a - particular flag may be denoted with a '!'. A rule - that contains a tcpflags specification can never - match a fragmented packet that has a non-zero - offset. See the frag option for details on - matching fragmented packets. - - icmptypes types - ICMP packets only. Match if the ICMP type is in - the list types. The list may be specified as any - combination of ranges or individual types - separated by commas. Both the numeric values and - the symbolic values listed below can be used. The - supported ICMP types are: - - - -Fajardo, et al. Standards Track [Page 50] - -RFC 6733 Diameter Base Protocol October 2012 - - - echo reply (0), destination unreachable (3), - source quench (4), redirect (5), echo request - (8), router advertisement (9), router - solicitation (10), time-to-live exceeded (11), IP - header bad (12), timestamp request (13), - timestamp reply (14), information request (15), - information reply (16), address mask request (17), - and address mask reply (18). - - There is one kind of packet that the access device MUST always - discard, that is an IP fragment with a fragment offset of one. This - is a valid packet, but it only has one use, to try to circumvent - firewalls. - - An access device that is unable to interpret or apply a deny rule - MUST terminate the session. An access device that is unable to - interpret or apply a permit rule MAY apply a more restrictive rule. - An access device MAY apply deny rules of its own before the supplied - rules, for example to protect the access device owner's - infrastructure. - -4.4. Grouped AVP Values - - The Diameter protocol allows AVP values of type 'Grouped'. This - implies that the Data field is actually a sequence of AVPs. It is - possible to include an AVP with a Grouped type within a Grouped type, - that is, to nest them. AVPs within an AVP of type Grouped have the - same padding requirements as non-Grouped AVPs, as defined in - Section 4.4. - - The AVP Code numbering space of all AVPs included in a Grouped AVP is - the same as for non-Grouped AVPs. Receivers of a Grouped AVP that - does not have the 'M' (mandatory) bit set and one or more of the - encapsulated AVPs within the group has the 'M' (mandatory) bit set - MAY simply be ignored if the Grouped AVP itself is unrecognized. The - rule applies even if the encapsulated AVP with its 'M' (mandatory) - bit set is further encapsulated within other sub-groups, i.e., other - Grouped AVPs embedded within the Grouped AVP. - - Every Grouped AVP definition MUST include a corresponding grammar, - using ABNF [RFC5234] (with modifications), as defined below. - - grouped-avp-def = "<" name ">" "::=" avp - - name-fmt = ALPHA *(ALPHA / DIGIT / "-") - - - - - - -Fajardo, et al. Standards Track [Page 51] - -RFC 6733 Diameter Base Protocol October 2012 - - - name = name-fmt - ; The name has to be the name of an AVP, - ; defined in the base or extended Diameter - ; specifications. - - avp = header *fixed *required *optional - - header = "<" "AVP-Header:" avpcode [vendor] ">" - - avpcode = 1*DIGIT - ; The AVP Code assigned to the Grouped AVP. - - vendor = 1*DIGIT - ; The Vendor-ID assigned to the Grouped AVP. - ; If absent, the default value of zero is - ; used. - -4.4.1. Example AVP with a Grouped Data Type - - The Example-AVP (AVP Code 999999) is of type Grouped and is used to - clarify how Grouped AVP values work. The Grouped Data field has the - following CCF grammar: - - Example-AVP ::= < AVP Header: 999999 > - { Origin-Host } - 1*{ Session-Id } - *[ AVP ] - - An Example-AVP with Grouped Data follows. - - The Origin-Host AVP (Section 6.3) is required. In this case: - - Origin-Host = "example.com". - - One or more Session-Ids must follow. Here there are two: - - Session-Id = - "grump.example.com:33041;23432;893;0AF3B81" - - Session-Id = - "grump.example.com:33054;23561;2358;0AF3B82" - - - - - - - - - - -Fajardo, et al. Standards Track [Page 52] - -RFC 6733 Diameter Base Protocol October 2012 - - - optional AVPs included are - - Recovery-Policy = <binary> - 2163bc1d0ad82371f6bc09484133c3f09ad74a0dd5346d54195a7cf0b35 - 2cabc881839a4fdcfbc1769e2677a4c1fb499284c5f70b48f58503a45c5 - c2d6943f82d5930f2b7c1da640f476f0e9c9572a50db8ea6e51e1c2c7bd - f8bb43dc995144b8dbe297ac739493946803e1cee3e15d9b765008a1b2a - cf4ac777c80041d72c01e691cf751dbf86e85f509f3988e5875dc905119 - 26841f00f0e29a6d1ddc1a842289d440268681e052b30fb638045f7779c - 1d873c784f054f688f5001559ecff64865ef975f3e60d2fd7966b8c7f92 - - Futuristic-Acct-Record = <binary> - fe19da5802acd98b07a5b86cb4d5d03f0314ab9ef1ad0b67111ff3b90a0 - 57fe29620bf3585fd2dd9fcc38ce62f6cc208c6163c008f4258d1bc88b8 - 17694a74ccad3ec69269461b14b2e7a4c111fb239e33714da207983f58c - 41d018d56fe938f3cbf089aac12a912a2f0d1923a9390e5f789cb2e5067 - d3427475e49968f841 - - The data for the optional AVPs is represented in hexadecimal form - since the format of these AVPs is not known at the time of definition - of the Example-AVP group nor (likely) at the time when the example - instance of this AVP is interpreted -- except by Diameter - implementations that support the same set of AVPs. The encoding - example illustrates how padding is used and how length fields are - calculated. Also, note that AVPs may be present in the Grouped AVP - value that the receiver cannot interpret (here, the Recover-Policy - and Futuristic-Acct-Record AVPs). The length of the Example-AVP is - the sum of all the length of the member AVPs, including their - padding, plus the Example-AVP header size. - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 53] - -RFC 6733 Diameter Base Protocol October 2012 - - - This AVP would be encoded as follows: - - 0 1 2 3 4 5 6 7 - +-------+-------+-------+-------+-------+-------+-------+-------+ - 0 | Example AVP Header (AVP Code = 999999), Length = 496 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 8 | Origin-Host AVP Header (AVP Code = 264), Length = 19 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 16 | 'e' | 'x' | 'a' | 'm' | 'p' | 'l' | 'e' | '.' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 24 | 'c' | 'o' | 'm' |Padding| Session-Id AVP Header | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 32 | (AVP Code = 263), Length = 49 | 'g' | 'r' | 'u' | 'm' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 72 | 'F' | '3' | 'B' | '8' | '1' |Padding|Padding|Padding| - +-------+-------+-------+-------+-------+-------+-------+-------+ - 80 | Session-Id AVP Header (AVP Code = 263), Length = 50 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 88 | 'g' | 'r' | 'u' | 'm' | 'p' | '.' | 'e' | 'x' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 120| '5' | '8' | ';' | '0' | 'A' | 'F' | '3' | 'B' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 128| '8' | '2' |Padding|Padding| Recovery-Policy Header (AVP | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 136| Code = 8341), Length = 223 | 0x21 | 0x63 | 0xbc | 0x1d | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 144| 0x0a | 0xd8 | 0x23 | 0x71 | 0xf6 | 0xbc | 0x09 | 0x48 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 352| 0x8c | 0x7f | 0x92 |Padding| Futuristic-Acct-Record Header | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 328|(AVP Code = 15930),Length = 137| 0xfe | 0x19 | 0xda | 0x58 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 336| 0x02 | 0xac | 0xd9 | 0x8b | 0x07 | 0xa5 | 0xb8 | 0xc6 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 488| 0xe4 | 0x99 | 0x68 | 0xf8 | 0x41 |Padding|Padding|Padding| - +-------+-------+-------+-------+-------+-------+-------+-------+ - - - - - - - -Fajardo, et al. Standards Track [Page 54] - -RFC 6733 Diameter Base Protocol October 2012 - - -4.5. Diameter Base Protocol AVPs - - The following table describes the Diameter AVPs defined in the base - protocol, their AVP Code values, types, and possible flag values. - - Due to space constraints, the short form DiamIdent is used to - represent DiameterIdentity. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 55] - -RFC 6733 Diameter Base Protocol October 2012 - - - +----------+ - | AVP Flag | - | rules | - |----+-----| - AVP Section | |MUST | - Attribute Name Code Defined Data Type |MUST| NOT | - -----------------------------------------|----+-----| - Acct- 85 9.8.2 Unsigned32 | M | V | - Interim-Interval | | | - Accounting- 483 9.8.7 Enumerated | M | V | - Realtime-Required | | | - Acct- 50 9.8.5 UTF8String | M | V | - Multi-Session-Id | | | - Accounting- 485 9.8.3 Unsigned32 | M | V | - Record-Number | | | - Accounting- 480 9.8.1 Enumerated | M | V | - Record-Type | | | - Acct- 44 9.8.4 OctetString| M | V | - Session-Id | | | - Accounting- 287 9.8.6 Unsigned64 | M | V | - Sub-Session-Id | | | - Acct- 259 6.9 Unsigned32 | M | V | - Application-Id | | | - Auth- 258 6.8 Unsigned32 | M | V | - Application-Id | | | - Auth-Request- 274 8.7 Enumerated | M | V | - Type | | | - Authorization- 291 8.9 Unsigned32 | M | V | - Lifetime | | | - Auth-Grace- 276 8.10 Unsigned32 | M | V | - Period | | | - Auth-Session- 277 8.11 Enumerated | M | V | - State | | | - Re-Auth-Request- 285 8.12 Enumerated | M | V | - Type | | | - Class 25 8.20 OctetString| M | V | - Destination-Host 293 6.5 DiamIdent | M | V | - Destination- 283 6.6 DiamIdent | M | V | - Realm | | | - Disconnect-Cause 273 5.4.3 Enumerated | M | V | - Error-Message 281 7.3 UTF8String | | V,M | - Error-Reporting- 294 7.4 DiamIdent | | V,M | - Host | | | - Event-Timestamp 55 8.21 Time | M | V | - Experimental- 297 7.6 Grouped | M | V | - Result | | | - -----------------------------------------|----+-----| - - - - -Fajardo, et al. Standards Track [Page 56] - -RFC 6733 Diameter Base Protocol October 2012 - - - +----------+ - | AVP Flag | - | rules | - |----+-----| - AVP Section | |MUST | - Attribute Name Code Defined Data Type |MUST| NOT | - -----------------------------------------|----+-----| - Experimental- 298 7.7 Unsigned32 | M | V | - Result-Code | | | - Failed-AVP 279 7.5 Grouped | M | V | - Firmware- 267 5.3.4 Unsigned32 | | V,M | - Revision | | | - Host-IP-Address 257 5.3.5 Address | M | V | - Inband-Security | M | V | - -Id 299 6.10 Unsigned32 | | | - Multi-Round- 272 8.19 Unsigned32 | M | V | - Time-Out | | | - Origin-Host 264 6.3 DiamIdent | M | V | - Origin-Realm 296 6.4 DiamIdent | M | V | - Origin-State-Id 278 8.16 Unsigned32 | M | V | - Product-Name 269 5.3.7 UTF8String | | V,M | - Proxy-Host 280 6.7.3 DiamIdent | M | V | - Proxy-Info 284 6.7.2 Grouped | M | V | - Proxy-State 33 6.7.4 OctetString| M | V | - Redirect-Host 292 6.12 DiamURI | M | V | - Redirect-Host- 261 6.13 Enumerated | M | V | - Usage | | | - Redirect-Max- 262 6.14 Unsigned32 | M | V | - Cache-Time | | | - Result-Code 268 7.1 Unsigned32 | M | V | - Route-Record 282 6.7.1 DiamIdent | M | V | - Session-Id 263 8.8 UTF8String | M | V | - Session-Timeout 27 8.13 Unsigned32 | M | V | - Session-Binding 270 8.17 Unsigned32 | M | V | - Session-Server- 271 8.18 Enumerated | M | V | - Failover | | | - Supported- 265 5.3.6 Unsigned32 | M | V | - Vendor-Id | | | - Termination- 295 8.15 Enumerated | M | V | - Cause | | | - User-Name 1 8.14 UTF8String | M | V | - Vendor-Id 266 5.3.3 Unsigned32 | M | V | - Vendor-Specific- 260 6.11 Grouped | M | V | - Application-Id | | | - -----------------------------------------|----+-----| - - - - - - -Fajardo, et al. Standards Track [Page 57] - -RFC 6733 Diameter Base Protocol October 2012 - - -5. Diameter Peers - - This section describes how Diameter nodes establish connections and - communicate with peers. - -5.1. Peer Connections - - Connections between diameter peers are established using their valid - DiameterIdentity. A Diameter node initiating a connection to a peer - MUST know the peer's DiameterIdentity. Methods for discovering a - Diameter peer can be found in Section 5.2. - - Although a Diameter node may have many possible peers with which it - is able to communicate, it may not be economical to have an - established connection to all of them. At a minimum, a Diameter node - SHOULD have an established connection with two peers per realm, known - as the primary and secondary peers. Of course, a node MAY have - additional connections, if it is deemed necessary. Typically, all - messages for a realm are sent to the primary peer but, in the event - that failover procedures are invoked, any pending requests are sent - to the secondary peer. However, implementations are free to load - balance requests between a set of peers. - - Note that a given peer MAY act as a primary for a given realm while - acting as a secondary for another realm. - - When a peer is deemed suspect, which could occur for various reasons, - including not receiving a DWA within an allotted time frame, no new - requests should be forwarded to the peer, but failover procedures are - invoked. When an active peer is moved to this mode, additional - connections SHOULD be established to ensure that the necessary number - of active connections exists. - - There are two ways that a peer is removed from the suspect peer list: - - 1. The peer is no longer reachable, causing the transport connection - to be shut down. The peer is moved to the closed state. - - 2. Three watchdog messages are exchanged with accepted round-trip - times, and the connection to the peer is considered stabilized. - - In the event the peer being removed is either the primary or - secondary, an alternate peer SHOULD replace the deleted peer and - assume the role of either primary or secondary. - - - - - - - -Fajardo, et al. Standards Track [Page 58] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.2. Diameter Peer Discovery - - Allowing for dynamic Diameter agent discovery makes possible simpler - and more robust deployment of Diameter services. In order to promote - interoperable implementations of Diameter peer discovery, the - following mechanisms (manual configuration and DNS) are described. - These are based on existing IETF standards. Both mechanisms MUST be - supported by all Diameter implementations; either MAY be used. - - There are two cases where Diameter peer discovery may be performed. - The first is when a Diameter client needs to discover a first-hop - Diameter agent. The second case is when a Diameter agent needs to - discover another agent for further handling of a Diameter operation. - In both cases, the following 'search order' is recommended: - - 1. The Diameter implementation consults its list of statically - (manually) configured Diameter agent locations. These will be - used if they exist and respond. - - 2. The Diameter implementation performs a NAPTR query for a server - in a particular realm. The Diameter implementation has to know, - in advance, in which realm to look for a Diameter agent. This - could be deduced, for example, from the 'realm' in an NAI on - which a Diameter implementation needed to perform a Diameter - operation. - - The NAPTR usage in Diameter follows the S-NAPTR DDDS application - [RFC3958] in which the SERVICE field includes tags for the - desired application and supported application protocol. The - application service tag for a Diameter application is 'aaa' and - the supported application protocol tags are 'diameter.tcp', - 'diameter.sctp', 'diameter.dtls', or 'diameter.tls.tcp' - [RFC6408]. - - The client can follow the resolution process defined by the - S-NAPTR DDDS [RFC3958] application to find a matching SRV, A, or - AAAA record of a suitable peer. The domain suffixes in the NAPTR - replacement field SHOULD match the domain of the original query. - An example can be found in Appendix B. - - 3. If no NAPTR records are found, the requester directly queries for - one of the following SRV records: for Diameter over TCP, use - "_diameter._tcp.realm"; for Diameter over TLS, use - "_diameters._tcp.realm"; for Diameter over SCTP, use - "_diameter._sctp.realm"; for Diameter over DTLS, use - "_diameters._sctp.realm". If SRV records are found, then the - requester can perform address record query (A RR's and/or AAAA - - - - -Fajardo, et al. Standards Track [Page 59] - -RFC 6733 Diameter Base Protocol October 2012 - - - RR's) for the target hostname specified in the SRV records - following the rules given in [RFC2782]. If no SRV records are - found, the requester gives up. - - If the server is using a site certificate, the domain name in the - NAPTR query and the domain name in the replacement field MUST both be - valid based on the site certificate handed out by the server in the - TLS/TCP and DTLS/SCTP or Internet Key Exchange Protocol (IKE) - exchange. Similarly, the domain name in the SRV query and the domain - name in the target in the SRV record MUST both be valid based on the - same site certificate. Otherwise, an attacker could modify the DNS - records to contain replacement values in a different domain, and the - client could not validate whether this was the desired behavior or - the result of an attack. - - Also, the Diameter peer MUST check to make sure that the discovered - peers are authorized to act in its role. Authentication via IKE or - TLS/TCP and DTLS/SCTP, or validation of DNS RRs via DNSSEC is not - sufficient to conclude this. For example, a web server may have - obtained a valid TLS/TCP and DTLS/SCTP certificate, and secured RRs - may be included in the DNS, but this does not imply that it is - authorized to act as a Diameter server. - - Authorization can be achieved, for example, by the configuration of a - Diameter server Certification Authority (CA). The server CA issues a - certificate to the Diameter server, which includes an Object - Identifier (OID) to indicate the subject is a Diameter server in the - Extended Key Usage extension [RFC5280]. This certificate is then - used during TLS/TCP, DTLS/SCTP, or IKE security negotiation. - However, note that, at the time of writing, no Diameter server - Certification Authorities exist. - - A dynamically discovered peer causes an entry in the peer table (see - Section 2.6) to be created. Note that entries created via DNS MUST - expire (or be refreshed) within the DNS Time to Live (TTL). If a - peer is discovered outside of the local realm, a routing table entry - (see Section 2.7) for the peer's realm is created. The routing table - entry's expiration MUST match the peer's expiration value. - -5.3. Capabilities Exchange - - When two Diameter peers establish a transport connection, they MUST - exchange the Capabilities Exchange messages, as specified in the peer - state machine (see Section 5.6). This message allows the discovery - of a peer's identity and its capabilities (protocol version number, - the identifiers of supported Diameter applications, security - mechanisms, etc.). - - - - -Fajardo, et al. Standards Track [Page 60] - -RFC 6733 Diameter Base Protocol October 2012 - - - The receiver only issues commands to its peers that have advertised - support for the Diameter application that defines the command. A - Diameter node MUST cache the supported Application Ids in order to - ensure that unrecognized commands and/or AVPs are not unnecessarily - sent to a peer. - - A receiver of a Capabilities-Exchange-Request (CER) message that does - not have any applications in common with the sender MUST return a - Capabilities-Exchange-Answer (CEA) with the Result-Code AVP set to - DIAMETER_NO_COMMON_APPLICATION and SHOULD disconnect the transport - layer connection. Note that receiving a CER or CEA from a peer - advertising itself as a relay (see Section 2.4) MUST be interpreted - as having common applications with the peer. - - The receiver of the Capabilities-Exchange-Request (CER) MUST - determine common applications by computing the intersection of its - own set of supported Application Ids against all of the - Application-Id AVPs (Auth-Application-Id, Acct-Application-Id, and - Vendor-Specific-Application-Id) present in the CER. The value of the - Vendor-Id AVP in the Vendor-Specific-Application-Id MUST NOT be used - during computation. The sender of the Capabilities-Exchange-Answer - (CEA) SHOULD include all of its supported applications as a hint to - the receiver regarding all of its application capabilities. - - Diameter implementations SHOULD first attempt to establish a TLS/TCP - and DTLS/SCTP connection prior to the CER/CEA exchange. This - protects the capabilities information of both peers. To support - older Diameter implementations that do not fully conform to this - document, the transport security MAY still be negotiated via an - Inband-Security AVP. In this case, the receiver of a Capabilities- - Exchange-Request (CER) message that does not have any security - mechanisms in common with the sender MUST return a Capabilities- - Exchange-Answer (CEA) with the Result-Code AVP set to - DIAMETER_NO_COMMON_SECURITY and SHOULD disconnect the transport layer - connection. - - CERs received from unknown peers MAY be silently discarded, or a CEA - MAY be issued with the Result-Code AVP set to DIAMETER_UNKNOWN_PEER. - In both cases, the transport connection is closed. If the local - policy permits receiving CERs from unknown hosts, a successful CEA - MAY be returned. If a CER from an unknown peer is answered with a - successful CEA, the lifetime of the peer entry is equal to the - lifetime of the transport connection. In case of a transport - failure, all the pending transactions destined to the unknown peer - can be discarded. - - The CER and CEA messages MUST NOT be proxied, redirected, or relayed. - - - - -Fajardo, et al. Standards Track [Page 61] - -RFC 6733 Diameter Base Protocol October 2012 - - - Since the CER/CEA messages cannot be proxied, it is still possible - that an upstream agent will receive a message for which it has no - available peers to handle the application that corresponds to the - Command Code. In such instances, the 'E' bit is set in the answer - message (Section 7) with the Result-Code AVP set to - DIAMETER_UNABLE_TO_DELIVER to inform the downstream agent to take - action (e.g., re-routing request to an alternate peer). - - With the exception of the Capabilities-Exchange-Request message, a - message of type Request that includes the Auth-Application-Id or - Acct-Application-Id AVPs, or a message with an application-specific - Command Code MAY only be forwarded to a host that has explicitly - advertised support for the application (or has advertised the Relay - Application Id). - -5.3.1. Capabilities-Exchange-Request - - The Capabilities-Exchange-Request (CER), indicated by the Command - Code set to 257 and the Command Flags' 'R' bit set, is sent to - exchange local capabilities. Upon detection of a transport failure, - this message MUST NOT be sent to an alternate peer. - - When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083], - which allow for connections to span multiple interfaces and multiple - IP addresses, the Capabilities-Exchange-Request message MUST contain - one Host-IP-Address AVP for each potential IP address that MAY be - locally used when transmitting Diameter messages. - - Message Format - - <CER> ::= < Diameter Header: 257, REQ > - { Origin-Host } - { Origin-Realm } - 1* { Host-IP-Address } - { Vendor-Id } - { Product-Name } - [ Origin-State-Id ] - * [ Supported-Vendor-Id ] - * [ Auth-Application-Id ] - * [ Inband-Security-Id ] - * [ Acct-Application-Id ] - * [ Vendor-Specific-Application-Id ] - [ Firmware-Revision ] - * [ AVP ] - - - - - - - -Fajardo, et al. Standards Track [Page 62] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.3.2. Capabilities-Exchange-Answer - - The Capabilities-Exchange-Answer (CEA), indicated by the Command Code - set to 257 and the Command Flags' 'R' bit cleared, is sent in - response to a CER message. - - When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083], - which allow connections to span multiple interfaces, hence, multiple - IP addresses, the Capabilities-Exchange-Answer message MUST contain - one Host-IP-Address AVP for each potential IP address that MAY be - locally used when transmitting Diameter messages. - - Message Format - - <CEA> ::= < Diameter Header: 257 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - 1* { Host-IP-Address } - { Vendor-Id } - { Product-Name } - [ Origin-State-Id ] - [ Error-Message ] - [ Failed-AVP ] - * [ Supported-Vendor-Id ] - * [ Auth-Application-Id ] - * [ Inband-Security-Id ] - * [ Acct-Application-Id ] - * [ Vendor-Specific-Application-Id ] - [ Firmware-Revision ] - * [ AVP ] - -5.3.3. Vendor-Id AVP - - The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains - the IANA "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value assigned to the Diameter Software vendor. It is - envisioned that the combination of the Vendor-Id, Product-Name - (Section 5.3.7), and Firmware-Revision (Section 5.3.4) AVPs may - provide useful debugging information. - - A Vendor-Id value of zero in the CER or CEA message is reserved and - indicates that this field is ignored. - - - - - - - - -Fajardo, et al. Standards Track [Page 63] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.3.4. Firmware-Revision AVP - - The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is - used to inform a Diameter peer of the firmware revision of the - issuing device. - - For devices that do not have a firmware revision (general-purpose - computers running Diameter software modules, for instance), the - revision of the Diameter software module may be reported instead. - -5.3.5. Host-IP-Address AVP - - The Host-IP-Address AVP (AVP Code 257) is of type Address and is used - to inform a Diameter peer of the sender's IP address. All source - addresses that a Diameter node expects to use with SCTP [RFC4960] or - DTLS/SCTP [RFC6083] MUST be advertised in the CER and CEA messages by - including a Host-IP-Address AVP for each address. - -5.3.6. Supported-Vendor-Id AVP - - The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and - contains the IANA "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value assigned to a vendor other than the device vendor - but including the application vendor. This is used in the CER and - CEA messages in order to inform the peer that the sender supports (a - subset of) the Vendor-Specific AVPs defined by the vendor identified - in this AVP. The value of this AVP MUST NOT be set to zero. - Multiple instances of this AVP containing the same value SHOULD NOT - be sent. - -5.3.7. Product-Name AVP - - The Product-Name AVP (AVP Code 269) is of type UTF8String and - contains the vendor-assigned name for the product. The Product-Name - AVP SHOULD remain constant across firmware revisions for the same - product. - -5.4. Disconnecting Peer Connections - - When a Diameter node disconnects one of its transport connections, - its peer cannot know the reason for the disconnect and will most - likely assume that a connectivity problem occurred or that the peer - has rebooted. In these cases, the peer may periodically attempt to - reconnect, as stated in Section 2.1. In the event that the - disconnect was a result of either a shortage of internal resources or - simply that the node in question has no intentions of forwarding any - Diameter messages to the peer in the foreseeable future, a periodic - - - - -Fajardo, et al. Standards Track [Page 64] - -RFC 6733 Diameter Base Protocol October 2012 - - - connection request would not be welcomed. The Disconnection-Reason - AVP contains the reason the Diameter node issued the Disconnect-Peer- - Request message. - - The Disconnect-Peer-Request message is used by a Diameter node to - inform its peer of its intent to disconnect the transport layer and - that the peer shouldn't reconnect unless it has a valid reason to do - so (e.g., message to be forwarded). Upon receipt of the message, the - Disconnect-Peer-Answer message is returned, which SHOULD contain an - error if messages have recently been forwarded, and are likely in - flight, which would otherwise cause a race condition. - - The receiver of the Disconnect-Peer-Answer message initiates the - transport disconnect. The sender of the Disconnect-Peer-Answer - message should be able to detect the transport closure and clean up - the connection. - -5.4.1. Disconnect-Peer-Request - - The Disconnect-Peer-Request (DPR), indicated by the Command Code set - to 282 and the Command Flags' 'R' bit set, is sent to a peer to - inform it of its intentions to shut down the transport connection. - Upon detection of a transport failure, this message MUST NOT be sent - to an alternate peer. - - Message Format - - <DPR> ::= < Diameter Header: 282, REQ > - { Origin-Host } - { Origin-Realm } - { Disconnect-Cause } - * [ AVP ] - -5.4.2. Disconnect-Peer-Answer - - The Disconnect-Peer-Answer (DPA), indicated by the Command Code set - to 282 and the Command Flags' 'R' bit cleared, is sent as a response - to the Disconnect-Peer-Request message. Upon receipt of this - message, the transport connection is shut down. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 65] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <DPA> ::= < Diameter Header: 282 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ Error-Message ] - [ Failed-AVP ] - * [ AVP ] - - -5.4.3. Disconnect-Cause AVP - - The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated. A - Diameter node MUST include this AVP in the Disconnect-Peer-Request - message to inform the peer of the reason for its intention to shut - down the transport connection. The following values are supported: - - REBOOTING 0 - A scheduled reboot is imminent. A receiver of a DPR with - above result code MAY attempt reconnection. - - BUSY 1 - The peer's internal resources are constrained, and it has - determined that the transport connection needs to be closed. - A receiver of a DPR with above result code SHOULD NOT attempt - reconnection. - - DO_NOT_WANT_TO_TALK_TO_YOU 2 - The peer has determined that it does not see a need for the - transport connection to exist, since it does not expect any - messages to be exchanged in the near future. A receiver of a - DPR with above result code SHOULD NOT attempt reconnection. - -5.5. Transport Failure Detection - - Given the nature of the Diameter protocol, it is recommended that - transport failures be detected as soon as possible. Detecting such - failures will minimize the occurrence of messages sent to unavailable - agents, resulting in unnecessary delays, and will provide better - failover performance. The Device-Watchdog-Request and Device- - Watchdog-Answer messages, defined in this section, are used to pro- - actively detect transport failures. - - - - - - - - -Fajardo, et al. Standards Track [Page 66] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.5.1. Device-Watchdog-Request - - The Device-Watchdog-Request (DWR), indicated by the Command Code set - to 280 and the Command Flags' 'R' bit set, is sent to a peer when no - traffic has been exchanged between two peers (see Section 5.5.3). - Upon detection of a transport failure, this message MUST NOT be sent - to an alternate peer. - - Message Format - - <DWR> ::= < Diameter Header: 280, REQ > - { Origin-Host } - { Origin-Realm } - [ Origin-State-Id ] - * [ AVP ] - -5.5.2. Device-Watchdog-Answer - - The Device-Watchdog-Answer (DWA), indicated by the Command Code set - to 280 and the Command Flags' 'R' bit cleared, is sent as a response - to the Device-Watchdog-Request message. - - Message Format - - <DWA> ::= < Diameter Header: 280 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ Error-Message ] - [ Failed-AVP ] - [ Origin-State-Id ] - * [ AVP ] - -5.5.3. Transport Failure Algorithm - - The transport failure algorithm is defined in [RFC3539]. All - Diameter implementations MUST support the algorithm defined in that - specification in order to be compliant to the Diameter base protocol. - -5.5.4. Failover and Failback Procedures - - In the event that a transport failure is detected with a peer, it is - necessary for all pending request messages to be forwarded to an - alternate agent, if possible. This is commonly referred to as - "failover". - - - - - - -Fajardo, et al. Standards Track [Page 67] - -RFC 6733 Diameter Base Protocol October 2012 - - - In order for a Diameter node to perform failover procedures, it is - necessary for the node to maintain a pending message queue for a - given peer. When an answer message is received, the corresponding - request is removed from the queue. The Hop-by-Hop Identifier field - is used to match the answer with the queued request. - - When a transport failure is detected, if possible, all messages in - the queue are sent to an alternate agent with the T flag set. On - booting a Diameter client or agent, the T flag is also set on any - remaining records in non-volatile storage that are still waiting to - be transmitted. An example of a case where it is not possible to - forward the message to an alternate server is when the message has a - fixed destination, and the unavailable peer is the message's final - destination (see Destination-Host AVP). Such an error requires that - the agent return an answer message with the 'E' bit set and the - Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. - - It is important to note that multiple identical requests or answers - MAY be received as a result of a failover. The End-to-End Identifier - field in the Diameter header along with the Origin-Host AVP MUST be - used to identify duplicate messages. - - As described in Section 2.1, a connection request should be - periodically attempted with the failed peer in order to re-establish - the transport connection. Once a connection has been successfully - established, messages can once again be forwarded to the peer. This - is commonly referred to as "failback". - -5.6. Peer State Machine - - This section contains a finite state machine that MUST be observed by - all Diameter implementations. Each Diameter node MUST follow the - state machine described below when communicating with each peer. - Multiple actions are separated by commas, and may continue on - succeeding lines, as space requires. Similarly, state and next state - may also span multiple lines, as space requires. - - This state machine is closely coupled with the state machine - described in [RFC3539], which is used to open, close, failover, - probe, and reopen transport connections. In particular, note that - [RFC3539] requires the use of watchdog messages to probe connections. - For Diameter, DWR and DWA messages are to be used. - - The I- prefix is used to represent the initiator (connecting) - connection, while the R- prefix is used to represent the responder - (listening) connection. The lack of a prefix indicates that the - event or action is the same regardless of the connection on which the - event occurred. - - - -Fajardo, et al. Standards Track [Page 68] - -RFC 6733 Diameter Base Protocol October 2012 - - - The stable states that a state machine may be in are Closed, I-Open, - and R-Open; all other states are intermediate. Note that I-Open and - R-Open are equivalent except for whether the initiator or responder - transport connection is used for communication. - - A CER message is always sent on the initiating connection immediately - after the connection request is successfully completed. In the case - of an election, one of the two connections will shut down. The - responder connection will survive if the Origin-Host of the local - Diameter entity is higher than that of the peer; the initiator - connection will survive if the peer's Origin-Host is higher. All - subsequent messages are sent on the surviving connection. Note that - the results of an election on one peer are guaranteed to be the - inverse of the results on the other. - - For TLS/TCP and DTLS/SCTP usage, a TLS/TCP and DTLS/SCTP handshake - SHOULD begin when both ends are in the closed state prior to any - Diameter message exchanges. The TLS/TCP and DTLS/SCTP connection - SHOULD be established before sending any CER or CEA message to secure - and protect the capabilities information of both peers. The TLS/TCP - and DTLS/SCTP connection SHOULD be disconnected when the state - machine moves to the closed state. When connecting to responders - that do not conform to this document (i.e., older Diameter - implementations that are not prepared to received TLS/TCP and DTLS/ - SCTP connections in the closed state), the initial TLS/TCP and DTLS/ - SCTP connection attempt will fail. The initiator MAY then attempt to - connect via TCP or SCTP and initiate the TLS/TCP and DTLS/SCTP - handshake when both ends are in the open state. If the handshake is - successful, all further messages will be sent via TLS/TCP and DTLS/ - SCTP. If the handshake fails, both ends move to the closed state. - - The state machine constrains only the behavior of a Diameter - implementation as seen by Diameter peers through events on the wire. - - Any implementation that produces equivalent results is considered - compliant. - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 69] - -RFC 6733 Diameter Base Protocol October 2012 - - - state event action next state - ----------------------------------------------------------------- - Closed Start I-Snd-Conn-Req Wait-Conn-Ack - R-Conn-CER R-Accept, R-Open - Process-CER, - R-Snd-CEA - - Wait-Conn-Ack I-Rcv-Conn-Ack I-Snd-CER Wait-I-CEA - I-Rcv-Conn-Nack Cleanup Closed - R-Conn-CER R-Accept, Wait-Conn-Ack/ - Process-CER Elect - Timeout Error Closed - - Wait-I-CEA I-Rcv-CEA Process-CEA I-Open - R-Conn-CER R-Accept, Wait-Returns - Process-CER, - Elect - I-Peer-Disc I-Disc Closed - I-Rcv-Non-CEA Error Closed - Timeout Error Closed - - Wait-Conn-Ack/ I-Rcv-Conn-Ack I-Snd-CER,Elect Wait-Returns - Elect I-Rcv-Conn-Nack R-Snd-CEA R-Open - R-Peer-Disc R-Disc Wait-Conn-Ack - R-Conn-CER R-Reject Wait-Conn-Ack/ - Elect - Timeout Error Closed - - Wait-Returns Win-Election I-Disc,R-Snd-CEA R-Open - I-Peer-Disc I-Disc, R-Open - R-Snd-CEA - I-Rcv-CEA R-Disc I-Open - R-Peer-Disc R-Disc Wait-I-CEA - R-Conn-CER R-Reject Wait-Returns - Timeout Error Closed - - R-Open Send-Message R-Snd-Message R-Open - R-Rcv-Message Process R-Open - R-Rcv-DWR Process-DWR, R-Open - R-Snd-DWA - R-Rcv-DWA Process-DWA R-Open - R-Conn-CER R-Reject R-Open - Stop R-Snd-DPR Closing - R-Rcv-DPR R-Snd-DPA Closing - R-Peer-Disc R-Disc Closed - - - - - - -Fajardo, et al. Standards Track [Page 70] - -RFC 6733 Diameter Base Protocol October 2012 - - - I-Open Send-Message I-Snd-Message I-Open - I-Rcv-Message Process I-Open - I-Rcv-DWR Process-DWR, I-Open - I-Snd-DWA - I-Rcv-DWA Process-DWA I-Open - R-Conn-CER R-Reject I-Open - Stop I-Snd-DPR Closing - I-Rcv-DPR I-Snd-DPA Closing - I-Peer-Disc I-Disc Closed - - Closing I-Rcv-DPA I-Disc Closed - R-Rcv-DPA R-Disc Closed - Timeout Error Closed - I-Peer-Disc I-Disc Closed - R-Peer-Disc R-Disc Closed - -5.6.1. Incoming Connections - - When a connection request is received from a Diameter peer, it is - not, in the general case, possible to know the identity of that peer - until a CER is received from it. This is because host and port - determine the identity of a Diameter peer; the source port of an - incoming connection is arbitrary. Upon receipt of a CER, the - identity of the connecting peer can be uniquely determined from the - Origin-Host. - - For this reason, a Diameter peer must employ logic separate from the - state machine to receive connection requests, accept them, and await - the CER. Once the CER arrives on a new connection, the Origin-Host - that identifies the peer is used to locate the state machine - associated with that peer, and the new connection and CER are passed - to the state machine as an R-Conn-CER event. - - The logic that handles incoming connections SHOULD close and discard - the connection if any message other than a CER arrives or if an - implementation-defined timeout occurs prior to receipt of CER. - - Because handling of incoming connections up to and including receipt - of a CER requires logic, separate from that of any individual state - machine associated with a particular peer, it is described separately - in this section rather than in the state machine above. - -5.6.2. Events - - Transitions and actions in the automaton are caused by events. In - this section, we will ignore the I- and R- prefixes, since the actual - event would be identical, but it would occur on one of two possible - connections. - - - -Fajardo, et al. Standards Track [Page 71] - -RFC 6733 Diameter Base Protocol October 2012 - - - Start The Diameter application has signaled that a - connection should be initiated with the peer. - - R-Conn-CER An acknowledgement is received stating that the - transport connection has been established, and the - associated CER has arrived. - - Rcv-Conn-Ack A positive acknowledgement is received confirming that - the transport connection is established. - - Rcv-Conn-Nack A negative acknowledgement was received stating that - the transport connection was not established. - - Timeout An application-defined timer has expired while waiting - for some event. - - Rcv-CER A CER message from the peer was received. - - Rcv-CEA A CEA message from the peer was received. - - Rcv-Non-CEA A message, other than a CEA, from the peer was - received. - - Peer-Disc A disconnection indication from the peer was received. - - Rcv-DPR A DPR message from the peer was received. - - Rcv-DPA A DPA message from the peer was received. - - Win-Election An election was held, and the local node was the - winner. - - Send-Message A message is to be sent. - - Rcv-Message A message other than CER, CEA, DPR, DPA, DWR, or DWA - was received. - - Stop The Diameter application has signaled that a - connection should be terminated (e.g., on system - shutdown). - -5.6.3. Actions - - Actions in the automaton are caused by events and typically indicate - the transmission of packets and/or an action to be taken on the - connection. In this section, we will ignore the I- and R- prefixes, - since the actual action would be identical, but it would occur on one - of two possible connections. - - - -Fajardo, et al. Standards Track [Page 72] - -RFC 6733 Diameter Base Protocol October 2012 - - - Snd-Conn-Req A transport connection is initiated with the peer. - - Accept The incoming connection associated with the R-Conn-CER - is accepted as the responder connection. - - Reject The incoming connection associated with the R-Conn-CER - is disconnected. - - Process-CER The CER associated with the R-Conn-CER is processed. - - Snd-CER A CER message is sent to the peer. - - Snd-CEA A CEA message is sent to the peer. - - Cleanup If necessary, the connection is shut down, and any - local resources are freed. - - Error The transport layer connection is disconnected, - either politely or abortively, in response to - an error condition. Local resources are freed. - - Process-CEA A received CEA is processed. - - Snd-DPR A DPR message is sent to the peer. - - Snd-DPA A DPA message is sent to the peer. - - Disc The transport layer connection is disconnected, - and local resources are freed. - - Elect An election occurs (see Section 5.6.4 for more - information). - - Snd-Message A message is sent. - - Snd-DWR A DWR message is sent. - - Snd-DWA A DWA message is sent. - - Process-DWR The DWR message is serviced. - - Process-DWA The DWA message is serviced. - - Process A message is serviced. - - - - - - - -Fajardo, et al. Standards Track [Page 73] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.6.4. The Election Process - - The election is performed on the responder. The responder compares - the Origin-Host received in the CER with its own Origin-Host as two - streams of octets. If the local Origin-Host lexicographically - succeeds the received Origin-Host, a Win-Election event is issued - locally. Diameter identities are in ASCII form; therefore, the - lexical comparison is consistent with DNS case insensitivity, where - octets that fall in the ASCII range 'a' through 'z' MUST compare - equally to their uppercase counterparts between 'A' and 'Z'. See - Appendix D for interactions between the Diameter protocol and - Internationalized Domain Name (IDNs). - - The winner of the election MUST close the connection it initiated. - Historically, maintaining the responder side of a connection was more - efficient than maintaining the initiator side. However, current - practices makes this distinction irrelevant. - -6. Diameter Message Processing - - This section describes how Diameter requests and answers are created - and processed. - -6.1. Diameter Request Routing Overview - - A request is sent towards its final destination using one of the - following three combinations of the Destination-Realm and - Destination-Host AVPs: - - o A request that is not able to be proxied (such as a CER) MUST NOT - contain either Destination-Realm or Destination-Host AVPs. - - o A request that needs to be sent to a home server serving a - specific realm, but not to a specific server (such as the first - request of a series of round trips), MUST contain a Destination- - Realm AVP but MUST NOT contain a Destination-Host AVP. For - Diameter clients, the value of the Destination-Realm AVP MAY be - extracted from the User-Name AVP, or other methods. - - o Otherwise, a request that needs to be sent to a specific home - server among those serving a given realm MUST contain both the - Destination-Realm and Destination-Host AVPs. - - The Destination-Host AVP is used as described above when the - destination of the request is fixed, which includes: - - o Authentication requests that span multiple round trips. - - - - -Fajardo, et al. Standards Track [Page 74] - -RFC 6733 Diameter Base Protocol October 2012 - - - o A Diameter message that uses a security mechanism that makes use - of a pre-established session key shared between the source and the - final destination of the message. - - o Server-initiated messages that MUST be received by a specific - Diameter client (e.g., access device), such as the Abort-Session- - Request message, which is used to request that a particular user's - session be terminated. - - Note that an agent can only forward a request to a host described in - the Destination-Host AVP if the host in question is included in its - peer table (see Section 2.6). Otherwise, the request is routed based - on the Destination-Realm only (see Section 6.1.6). - - When a message is received, the message is processed in the following - order: - - o If the message is destined for the local host, the procedures - listed in Section 6.1.4 are followed. - - o If the message is intended for a Diameter peer with whom the local - host is able to directly communicate, the procedures listed in - Section 6.1.5 are followed. This is known as "Request - Forwarding". - - o The procedure listed in Section 6.1.6 is followed, which is known - as "Request Routing". - - o If none of the above are successful, an answer is returned with - the Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the 'E' - bit set. - - For routing of Diameter messages to work within an administrative - domain, all Diameter nodes within the realm MUST be peers. - - The overview contained in this section (6.1) is intended to provide - general guidelines to Diameter developers. Implementations are free - to use different methods than the ones described here as long as they - conform to the requirements specified in Sections 6.1.1 through - 6.1.9. See Section 7 for more details on error handling. - -6.1.1. Originating a Request - - When creating a request, in addition to any other procedures - described in the application definition for that specific request, - the following procedures MUST be followed: - - - - - -Fajardo, et al. Standards Track [Page 75] - -RFC 6733 Diameter Base Protocol October 2012 - - - o the Command Code is set to the appropriate value; - - o the 'R' bit is set; - - o the End-to-End Identifier is set to a locally unique value; - - o the Origin-Host and Origin-Realm AVPs MUST be set to the - appropriate values, used to identify the source of the message; - and - - o the Destination-Host and Destination-Realm AVPs MUST be set to the - appropriate values, as described in Section 6.1. - -6.1.2. Sending a Request - - When sending a request, originated either locally or as the result of - a forwarding or routing operation, the following procedures SHOULD be - followed: - - o The Hop-by-Hop Identifier SHOULD be set to a locally unique value. - - o The message SHOULD be saved in the list of pending requests. - - Other actions to perform on the message based on the particular role - the agent is playing are described in the following sections. - -6.1.3. Receiving Requests - - A relay or proxy agent MUST check for forwarding loops when receiving - requests. A loop is detected if the server finds its own identity in - a Route-Record AVP. When such an event occurs, the agent MUST answer - with the Result-Code AVP set to DIAMETER_LOOP_DETECTED. - -6.1.4. Processing Local Requests - - A request is known to be for local consumption when one of the - following conditions occurs: - - o The Destination-Host AVP contains the local host's identity; - - o The Destination-Host AVP is not present, the Destination-Realm AVP - contains a realm the server is configured to process locally, and - the Diameter application is locally supported; or - - o Both the Destination-Host and the Destination-Realm are not - present. - - - - - -Fajardo, et al. Standards Track [Page 76] - -RFC 6733 Diameter Base Protocol October 2012 - - - When a request is locally processed, the rules in Section 6.2 should - be used to generate the corresponding answer. - -6.1.5. Request Forwarding - - Request forwarding is done using the Diameter peer table. The - Diameter peer table contains all of the peers with which the local - node is able to directly communicate. - - When a request is received, and the host encoded in the Destination- - Host AVP is one that is present in the peer table, the message SHOULD - be forwarded to the peer. - -6.1.6. Request Routing - - Diameter request message routing is done via realms and Application - Ids. A Diameter message that may be forwarded by Diameter agents - (proxies, redirect agents, or relay agents) MUST include the target - realm in the Destination-Realm AVP. Request routing SHOULD rely on - the Destination-Realm AVP and the Application Id present in the - request message header to aid in the routing decision. The realm MAY - be retrieved from the User-Name AVP, which is in the form of a - Network Access Identifier (NAI). The realm portion of the NAI is - inserted in the Destination-Realm AVP. - - Diameter agents MAY have a list of locally supported realms and - applications, and they MAY have a list of externally supported realms - and applications. When a request is received that includes a realm - and/or application that is not locally supported, the message is - routed to the peer configured in the routing table (see Section 2.7). - - Realm names and Application Ids are the minimum supported routing - criteria, additional information may be needed to support redirect - semantics. - -6.1.7. Predictive Loop Avoidance - - Before forwarding or routing a request, Diameter agents, in addition - to performing the processing described in Section 6.1.3, SHOULD check - for the presence of a candidate route's peer identity in any of the - Route-Record AVPs. In the event of the agent detecting the presence - of a candidate route's peer identity in a Route-Record AVP, the agent - MUST ignore such a route for the Diameter request message and attempt - alternate routes if any exist. In case all the candidate routes are - eliminated by the above criteria, the agent SHOULD return a - DIAMETER_UNABLE_TO_DELIVER message. - - - - - -Fajardo, et al. Standards Track [Page 77] - -RFC 6733 Diameter Base Protocol October 2012 - - -6.1.8. Redirecting Requests - - When a redirect agent receives a request whose routing entry is set - to REDIRECT, it MUST reply with an answer message with the 'E' bit - set, while maintaining the Hop-by-Hop Identifier in the header, and - include the Result-Code AVP to DIAMETER_REDIRECT_INDICATION. Each of - the servers associated with the routing entry are added in a separate - Redirect-Host AVP. - - +------------------+ - | Diameter | - | Redirect Agent | - +------------------+ - ^ | 2. command + 'E' bit - 1. Request | | Result-Code = - [email protected] | | DIAMETER_REDIRECT_INDICATION + - | | Redirect-Host AVP(s) - | v - +-------------+ 3. Request +-------------+ - | example.com |------------->| example.net | - | Relay | | Diameter | - | Agent |<-------------| Server | - +-------------+ 4. Answer +-------------+ - - Figure 5: Diameter Redirect Agent - - The receiver of an answer message with the 'E' bit set and the - Result-Code AVP set to DIAMETER_REDIRECT_INDICATION uses the Hop-by- - Hop Identifier in the Diameter header to identify the request in the - pending message queue (see Section 5.5.4) that is to be redirected. - If no transport connection exists with the new peer, one is created, - and the request is sent directly to it. - - Multiple Redirect-Host AVPs are allowed. The receiver of the answer - message with the 'E' bit set selects exactly one of these hosts as - the destination of the redirected message. - - When the Redirect-Host-Usage AVP included in the answer message has a - non-zero value, a route entry for the redirect indications is created - and cached by the receiver. The redirect usage for such a route - entry is set by the value of Redirect-Host-Usage AVP and the lifetime - of the cached route entry is set by Redirect-Max-Cache-Time AVP - value. - - It is possible that multiple redirect indications can create multiple - cached route entries differing only in their redirect usage and the - peer to forward messages to. As an example, two(2) route entries - that are created by two(2) redirect indications results in two(2) - - - -Fajardo, et al. Standards Track [Page 78] - -RFC 6733 Diameter Base Protocol October 2012 - - - cached routes for the same realm and Application Id. However, one - has a redirect usage of ALL_SESSION, where matching requests will be - forwarded to one peer; the other has a redirect usage of ALL_REALM, - where request are forwarded to another peer. Therefore, an incoming - request that matches the realm and Application Id of both routes will - need additional resolution. In such a case, a routing precedence - rule MUST be used against the redirect usage value to resolve the - contention. The precedence rule can be found in Section 6.13. - -6.1.9. Relaying and Proxying Requests - - A relay or proxy agent MUST append a Route-Record AVP to all requests - forwarded. The AVP contains the identity of the peer from which the - request was received. - - The Hop-by-Hop Identifier in the request is saved and replaced with a - locally unique value. The source of the request is also saved, which - includes the IP address, port, and protocol. - - A relay or proxy agent MAY include the Proxy-Info AVP in requests if - it requires access to any local state information when the - corresponding response is received. The Proxy-Info AVP has security - implications as state information is distributed to other entities. - As such, it is RECOMMENDED that the content of the Proxy-Info AVP be - protected with cryptographic mechanisms, for example, by using a - keyed message digest such as HMAC-SHA1 [RFC2104]. Such a mechanism, - however, requires the management of keys, although only locally at - the Diameter server. Still, a full description of the management of - the keys used to protect the Proxy-Info AVP is beyond the scope of - this document. Below is a list of common recommendations: - - o The keys should be generated securely following the randomness - recommendations in [RFC4086]. - - o The keys and cryptographic protection algorithms should be at - least 128 bits in strength. - - o The keys should not be used for any other purpose than generating - and verifying instances of the Proxy-Info AVP. - - o The keys should be changed regularly. - - o The keys should be changed if the AVP format or cryptographic - protection algorithms change. - - The message is then forwarded to the next hop, as identified in the - routing table. - - - - -Fajardo, et al. Standards Track [Page 79] - -RFC 6733 Diameter Base Protocol October 2012 - - - Figure 6 provides an example of message routing using the procedures - listed in these sections. - - (Origin-Host=nas.example.net) (Origin-Host=nas.example.net) - (Origin-Realm=example.net) (Origin-Realm=example.net) - (Destination-Realm=example.com) (Destination-Realm=example.com) - (Route-Record=nas.example.net) - +------+ ------> +------+ ------> +------+ - | | (Request) | | (Request) | | - | NAS +-------------------+ DRL +-------------------+ HMS | - | | | | | | - +------+ <------ +------+ <------ +------+ - example.net (Answer) example.net (Answer) example.com - (Origin-Host=hms.example.com) (Origin-Host=hms.example.com) - (Origin-Realm=example.com) (Origin-Realm=example.com) - - Figure 6: Routing of Diameter messages - - Relay and proxy agents are not required to perform full inspection of - incoming messages. At a minimum, validation of the message header - and relevant routing AVPs has to be done when relaying messages. - Proxy agents may optionally perform more in-depth message validation - for applications in which it is interested. - -6.2. Diameter Answer Processing - - When a request is locally processed, the following procedures MUST be - applied to create the associated answer, in addition to any - additional procedures that MAY be discussed in the Diameter - application defining the command: - - o The same Hop-by-Hop Identifier in the request is used in the - answer. - - o The local host's identity is encoded in the Origin-Host AVP. - - o The Destination-Host and Destination-Realm AVPs MUST NOT be - present in the answer message. - - o The Result-Code AVP is added with its value indicating success or - failure. - - o If the Session-Id is present in the request, it MUST be included - in the answer. - - o Any Proxy-Info AVPs in the request MUST be added to the answer - message, in the same order they were present in the request. - - - - -Fajardo, et al. Standards Track [Page 80] - -RFC 6733 Diameter Base Protocol October 2012 - - - o The 'P' bit is set to the same value as the one in the request. - - o The same End-to-End identifier in the request is used in the - answer. - - Note that the error messages (see Section 7) are also subjected to - the above processing rules. - -6.2.1. Processing Received Answers - - A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an - answer received against the list of pending requests. The - corresponding message should be removed from the list of pending - requests. It SHOULD ignore answers received that do not match a - known Hop-by-Hop Identifier. - -6.2.2. Relaying and Proxying Answers - - If the answer is for a request that was proxied or relayed, the agent - MUST restore the original value of the Diameter header's Hop-by-Hop - Identifier field. - - If the last Proxy-Info AVP in the message is targeted to the local - Diameter server, the AVP MUST be removed before the answer is - forwarded. - - If a relay or proxy agent receives an answer with a Result-Code AVP - indicating a failure, it MUST NOT modify the contents of the AVP. - Any additional local errors detected SHOULD be logged but not - reflected in the Result-Code AVP. If the agent receives an answer - message with a Result-Code AVP indicating success, and it wishes to - modify the AVP to indicate an error, it MUST modify the Result-Code - AVP to contain the appropriate error in the message destined towards - the access device as well as include the Error-Reporting-Host AVP; it - MUST also issue an STR on behalf of the access device towards the - Diameter server. - - The agent MUST then send the answer to the host that it received the - original request from. - -6.3. Origin-Host AVP - - The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and - it MUST be present in all Diameter messages. This AVP identifies the - endpoint that originated the Diameter message. Relay agents MUST NOT - modify this AVP. - - - - - -Fajardo, et al. Standards Track [Page 81] - -RFC 6733 Diameter Base Protocol October 2012 - - - The value of the Origin-Host AVP is guaranteed to be unique within a - single host. - - Note that the Origin-Host AVP may resolve to more than one address as - the Diameter peer may support more than one address. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.4. Origin-Realm AVP - - The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity. - This AVP contains the Realm of the originator of any Diameter message - and MUST be present in all messages. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.5. Destination-Host AVP - - The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity. - This AVP MUST be present in all unsolicited agent initiated messages, - MAY be present in request messages, and MUST NOT be present in answer - messages. - - The absence of the Destination-Host AVP will cause a message to be - sent to any Diameter server supporting the application within the - realm specified in Destination-Realm AVP. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.6. Destination-Realm AVP - - The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity - and contains the realm to which the message is to be routed. The - Destination-Realm AVP MUST NOT be present in answer messages. - Diameter clients insert the realm portion of the User-Name AVP. - Diameter servers initiating a request message use the value of the - Origin-Realm AVP from a previous message received from the intended - target host (unless it is known a priori). When present, the - Destination-Realm AVP is used to perform message routing decisions. - - The CCF for a request message that includes the Destination-Realm AVP - SHOULD list the Destination-Realm AVP as a required AVP (an AVP - indicated as {AVP}); otherwise, the message is inherently a non- - routable message. - - - - -Fajardo, et al. Standards Track [Page 82] - -RFC 6733 Diameter Base Protocol October 2012 - - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.7. Routing AVPs - - The AVPs defined in this section are Diameter AVPs used for routing - purposes. These AVPs change as Diameter messages are processed by - agents. - -6.7.1. Route-Record AVP - - The Route-Record AVP (AVP Code 282) is of type DiameterIdentity. The - identity added in this AVP MUST be the same as the one received in - the Origin-Host of the Capabilities Exchange message. - -6.7.2. Proxy-Info AVP - - The Proxy-Info AVP (AVP Code 284) is of type Grouped. This AVP - contains the identity and local state information of the Diameter - node that creates and adds it to a message. The Grouped Data field - has the following CCF grammar: - - Proxy-Info ::= < AVP Header: 284 > - { Proxy-Host } - { Proxy-State } - * [ AVP ] - -6.7.3. Proxy-Host AVP - - The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity. This - AVP contains the identity of the host that added the Proxy-Info AVP. - -6.7.4. Proxy-State AVP - - The Proxy-State AVP (AVP Code 33) is of type OctetString. It - contains state information that would otherwise be stored at the - Diameter entity that created it. As such, this AVP MUST be treated - as opaque data by other Diameter entities. - -6.8. Auth-Application-Id AVP - - The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and - is used in order to advertise support of the Authentication and - Authorization portion of an application (see Section 2.4). If - present in a message other than CER and CEA, the value of the Auth- - Application-Id AVP MUST match the Application Id present in the - Diameter message header. - - - - -Fajardo, et al. Standards Track [Page 83] - -RFC 6733 Diameter Base Protocol October 2012 - - -6.9. Acct-Application-Id AVP - - The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and - is used in order to advertise support of the accounting portion of an - application (see Section 2.4). If present in a message other than - CER and CEA, the value of the Acct-Application-Id AVP MUST match the - Application Id present in the Diameter message header. - -6.10. Inband-Security-Id AVP - - The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and - is used in order to advertise support of the security portion of the - application. The use of this AVP in CER and CEA messages is NOT - RECOMMENDED. Instead, discovery of a Diameter entity's security - capabilities can be done either through static configuration or via - Diameter Peer Discovery as described in Section 5.2. - - The following values are supported: - - - NO_INBAND_SECURITY 0 - - This peer does not support TLS/TCP and DTLS/SCTP. This is the - default value, if the AVP is omitted. - - TLS 1 - - This node supports TLS/TCP [RFC5246] and DTLS/SCTP [RFC6083] - security. - -6.11. Vendor-Specific-Application-Id AVP - - The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type - Grouped and is used to advertise support of a vendor-specific - Diameter application. Exactly one instance of either Auth- - Application-Id or Acct-Application-Id AVP MUST be present. The - Application Id carried by either Auth-Application-Id or Acct- - Application-Id AVP MUST comply with vendor-specific Application Id - assignment described in Section 11.3. It MUST also match the - Application Id present in the Diameter header except when used in a - CER or CEA message. - - The Vendor-Id AVP is an informational AVP pertaining to the vendor - who may have authorship of the vendor-specific Diameter application. - It MUST NOT be used as a means of defining a completely separate - vendor-specific Application Id space. - - - - - -Fajardo, et al. Standards Track [Page 84] - -RFC 6733 Diameter Base Protocol October 2012 - - - The Vendor-Specific-Application-Id AVP SHOULD be placed as close to - the Diameter header as possible. - - AVP Format - - <Vendor-Specific-Application-Id> ::= < AVP Header: 260 > - { Vendor-Id } - [ Auth-Application-Id ] - [ Acct-Application-Id ] - - A Vendor-Specific-Application-Id AVP MUST contain exactly one of - either Auth-Application-Id or Acct-Application-Id. If a Vendor- - Specific-Application-Id is received without one of these two AVPs, - then the recipient SHOULD issue an answer with a Result-Code set to - DIAMETER_MISSING_AVP. The answer SHOULD also include a Failed-AVP, - which MUST contain an example of an Auth-Application-Id AVP and an - Acct-Application-Id AVP. - - If a Vendor-Specific-Application-Id is received that contains both - Auth-Application-Id and Acct-Application-Id, then the recipient MUST - issue an answer with Result-Code set to - DIAMETER_AVP_OCCURS_TOO_MANY_TIMES. The answer MUST also include a - Failed-AVP, which MUST contain the received Auth-Application-Id AVP - and Acct-Application-Id AVP. - -6.12. Redirect-Host AVP - - The Redirect-Host AVP (AVP Code 292) is of type DiameterURI. One or - more instances of this AVP MUST be present if the answer message's - 'E' bit is set and the Result-Code AVP is set to - DIAMETER_REDIRECT_INDICATION. - - Upon receiving the above, the receiving Diameter node SHOULD forward - the request directly to one of the hosts identified in these AVPs. - The server contained in the selected Redirect-Host AVP SHOULD be used - for all messages matching the criteria set by the Redirect-Host-Usage - AVP. - -6.13. Redirect-Host-Usage AVP - - The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated. - This AVP MAY be present in answer messages whose 'E' bit is set and - the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION. - - When present, this AVP provides hints about how the routing entry - resulting from the Redirect-Host is to be used. The following values - are supported: - - - - -Fajardo, et al. Standards Track [Page 85] - -RFC 6733 Diameter Base Protocol October 2012 - - - DONT_CACHE 0 - - The host specified in the Redirect-Host AVP SHOULD NOT be cached. - This is the default value. - - ALL_SESSION 1 - - All messages within the same session, as defined by the same value - of the Session-ID AVP SHOULD be sent to the host specified in the - Redirect-Host AVP. - - ALL_REALM 2 - - All messages destined for the realm requested SHOULD be sent to - the host specified in the Redirect-Host AVP. - - REALM_AND_APPLICATION 3 - - All messages for the application requested to the realm specified - SHOULD be sent to the host specified in the Redirect-Host AVP. - - ALL_APPLICATION 4 - - All messages for the application requested SHOULD be sent to the - host specified in the Redirect-Host AVP. - - ALL_HOST 5 - - All messages that would be sent to the host that generated the - Redirect-Host SHOULD be sent to the host specified in the - Redirect-Host AVP. - - ALL_USER 6 - - All messages for the user requested SHOULD be sent to the host - specified in the Redirect-Host AVP. - - When multiple cached routes are created by redirect indications and - they differ only in redirect usage and peers to forward requests to - (see Section 6.1.8), a precedence rule MUST be applied to the - redirect usage values of the cached routes during normal routing to - resolve contentions that may occur. The precedence rule is the order - that dictate which redirect usage should be considered before any - other as they appear. The order is as follows: - - - - - - - -Fajardo, et al. Standards Track [Page 86] - -RFC 6733 Diameter Base Protocol October 2012 - - - 1. ALL_SESSION - - 2. ALL_USER - - 3. REALM_AND_APPLICATION - - 4. ALL_REALM - - 5. ALL_APPLICATION - - 6. ALL_HOST - -6.14. Redirect-Max-Cache-Time AVP - - The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32. - This AVP MUST be present in answer messages whose 'E' bit is set, - whose Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION, and - whose Redirect-Host-Usage AVP set to a non-zero value. - - This AVP contains the maximum number of seconds the peer and route - table entries, created as a result of the Redirect-Host, SHOULD be - cached. Note that once a host is no longer reachable, any associated - cache, peer, and routing table entries MUST be deleted. - -7. Error Handling - - There are two different types of errors in Diameter; protocol errors - and application errors. A protocol error is one that occurs at the - base protocol level and MAY require per-hop attention (e.g., a - message routing error). Application errors, on the other hand, - generally occur due to a problem with a function specified in a - Diameter application (e.g., user authentication, missing AVP). - - Result-Code AVP values that are used to report protocol errors MUST - only be present in answer messages whose 'E' bit is set. When a - request message is received that causes a protocol error, an answer - message is returned with the 'E' bit set, and the Result-Code AVP is - set to the appropriate protocol error value. As the answer is sent - back towards the originator of the request, each proxy or relay agent - MAY take action on the message. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 87] - -RFC 6733 Diameter Base Protocol October 2012 - - - 1. Request +---------+ Link Broken - +-------------------------->|Diameter |----///----+ - | +---------------------| | v - +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+ - |Diameter |<-+ (Unable to Forward) +---------+ |Diameter| - | | | Home | - | Relay 1 |--+ +---------+ | Server | - +---------+ | 3. Request |Diameter | +--------+ - +-------------------->| | ^ - | Relay 3 |-----------+ - +---------+ - - Figure 7: Example of Protocol Error Causing Answer Message - - Figure 7 provides an example of a message forwarded upstream by a - Diameter relay. When the message is received by Relay 2, and it - detects that it cannot forward the request to the home server, an - answer message is returned with the 'E' bit set and the Result-Code - AVP set to DIAMETER_UNABLE_TO_DELIVER. Given that this error falls - within the protocol error category, Relay 1 would take special - action, and given the error, attempt to route the message through its - alternate Relay 3. - - +---------+ 1. Request +---------+ 2. Request +---------+ - | Access |------------>|Diameter |------------>|Diameter | - | | | | | Home | - | Device |<------------| Relay |<------------| Server | - +---------+ 4. Answer +---------+ 3. Answer +---------+ - (Missing AVP) (Missing AVP) - - Figure 8: Example of Application Error Answer Message - - Figure 8 provides an example of a Diameter message that caused an - application error. When application errors occur, the Diameter - entity reporting the error clears the 'R' bit in the Command Flags - and adds the Result-Code AVP with the proper value. Application - errors do not require any proxy or relay agent involvement; - therefore, the message would be forwarded back to the originator of - the request. - - In the case where the answer message itself contains errors, any - related session SHOULD be terminated by sending an STR or ASR - message. The Termination-Cause AVP in the STR MAY be filled with the - appropriate value to indicate the cause of the error. An application - MAY also send an application-specific request instead of an STR or - ASR message to signal the error in the case where no state is - maintained or to allow for some form of error recovery with the - corresponding Diameter entity. - - - -Fajardo, et al. Standards Track [Page 88] - -RFC 6733 Diameter Base Protocol October 2012 - - - There are certain Result-Code AVP application errors that require - additional AVPs to be present in the answer. In these cases, the - Diameter node that sets the Result-Code AVP to indicate the error - MUST add the AVPs. Examples are as follows: - - o A request with an unrecognized AVP is received with the 'M' bit - (Mandatory bit) set causes an answer to be sent with the Result- - Code AVP set to DIAMETER_AVP_UNSUPPORTED and the Failed-AVP AVP - containing the offending AVP. - - o A request with an AVP that is received with an unrecognized value - causes an answer to be returned with the Result-Code AVP set to - DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the - AVP causing the error. - - o A received command that is missing AVPs that are defined as - required in the commands CCF; examples are AVPs indicated as - {AVP}. The receiver issues an answer with the Result-Code set to - DIAMETER_MISSING_AVP and creates an AVP with the AVP Code and - other fields set as expected in the missing AVP. The created AVP - is then added to the Failed-AVP AVP. - - The Result-Code AVP describes the error that the Diameter node - encountered in its processing. In case there are multiple errors, - the Diameter node MUST report only the first error it encountered - (detected possibly in some implementation-dependent order). The - specific errors that can be described by this AVP are described in - the following section. - -7.1. Result-Code AVP - - The Result-Code AVP (AVP Code 268) is of type Unsigned32 and - indicates whether a particular request was completed successfully or - an error occurred. All Diameter answer messages in IETF-defined - Diameter application specifications MUST include one Result-Code AVP. - A non-successful Result-Code AVP (one containing a non-2xxx value - other than DIAMETER_REDIRECT_INDICATION) MUST include the Error- - Reporting-Host AVP if the host setting the Result-Code AVP is - different from the identity encoded in the Origin-Host AVP. - - The Result-Code data field contains an IANA-managed 32-bit address - space representing errors (see Section 11.3.2). Diameter provides - the following classes of errors, all identified by the thousands - digit in the decimal notation: - - - - - - - -Fajardo, et al. Standards Track [Page 89] - -RFC 6733 Diameter Base Protocol October 2012 - - - o 1xxx (Informational) - - o 2xxx (Success) - - o 3xxx (Protocol Errors) - - o 4xxx (Transient Failures) - - o 5xxx (Permanent Failure) - - An unrecognized class (one whose first digit is not defined in this - section) MUST be handled as a permanent failure. - -7.1.1. Informational - - Errors that fall within this category are used to inform the - requester that a request could not be satisfied, and additional - action is required on its part before access is granted. - - DIAMETER_MULTI_ROUND_AUTH 1001 - - This informational error is returned by a Diameter server to - inform the access device that the authentication mechanism being - used requires multiple round trips, and a subsequent request needs - to be issued in order for access to be granted. - -7.1.2. Success - - Errors that fall within the Success category are used to inform a - peer that a request has been successfully completed. - - DIAMETER_SUCCESS 2001 - - The request was successfully completed. - - DIAMETER_LIMITED_SUCCESS 2002 - - When returned, the request was successfully completed, but - additional processing is required by the application in order to - provide service to the user. - -7.1.3. Protocol Errors - - Errors that fall within the Protocol Error category SHOULD be treated - on a per-hop basis, and Diameter proxies MAY attempt to correct the - error, if it is possible. Note that these errors MUST only be used - in answer messages whose 'E' bit is set. - - - - -Fajardo, et al. Standards Track [Page 90] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_COMMAND_UNSUPPORTED 3001 - - This error code is used when a Diameter entity receives a message - with a Command Code that it does not support. - - DIAMETER_UNABLE_TO_DELIVER 3002 - - This error is given when Diameter cannot deliver the message to - the destination, either because no host within the realm - supporting the required application was available to process the - request or because the Destination-Host AVP was given without the - associated Destination-Realm AVP. - - DIAMETER_REALM_NOT_SERVED 3003 - - The intended realm of the request is not recognized. - - DIAMETER_TOO_BUSY 3004 - - When returned, a Diameter node SHOULD attempt to send the message - to an alternate peer. This error MUST only be used when a - specific server is requested, and it cannot provide the requested - service. - - DIAMETER_LOOP_DETECTED 3005 - - An agent detected a loop while trying to get the message to the - intended recipient. The message MAY be sent to an alternate peer, - if one is available, but the peer reporting the error has - identified a configuration problem. - - DIAMETER_REDIRECT_INDICATION 3006 - - A redirect agent has determined that the request could not be - satisfied locally, and the initiator of the request SHOULD direct - the request directly to the server, whose contact information has - been added to the response. When set, the Redirect-Host AVP MUST - be present. - - DIAMETER_APPLICATION_UNSUPPORTED 3007 - - A request was sent for an application that is not supported. - - DIAMETER_INVALID_HDR_BITS 3008 - - A request was received whose bits in the Diameter header were set - either to an invalid combination or to a value that is - inconsistent with the Command Code's definition. - - - -Fajardo, et al. Standards Track [Page 91] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_INVALID_AVP_BITS 3009 - - A request was received that included an AVP whose flag bits are - set to an unrecognized value or that is inconsistent with the - AVP's definition. - - DIAMETER_UNKNOWN_PEER 3010 - - A CER was received from an unknown peer. - -7.1.4. Transient Failures - - Errors that fall within the transient failures category are used to - inform a peer that the request could not be satisfied at the time it - was received but MAY be able to satisfy the request in the future. - Note that these errors MUST be used in answer messages whose 'E' bit - is not set. - - DIAMETER_AUTHENTICATION_REJECTED 4001 - - The authentication process for the user failed, most likely due to - an invalid password used by the user. Further attempts MUST only - be tried after prompting the user for a new password. - - DIAMETER_OUT_OF_SPACE 4002 - - A Diameter node received the accounting request but was unable to - commit it to stable storage due to a temporary lack of space. - - ELECTION_LOST 4003 - - The peer has determined that it has lost the election process and - has therefore disconnected the transport connection. - -7.1.5. Permanent Failures - - Errors that fall within the permanent failures category are used to - inform the peer that the request failed and should not be attempted - again. Note that these errors SHOULD be used in answer messages - whose 'E' bit is not set. In error conditions where it is not - possible or efficient to compose application-specific answer grammar, - answer messages with the 'E' bit set and which comply to the grammar - described in Section 7.2 MAY also be used for permanent errors. - - - - - - - - -Fajardo, et al. Standards Track [Page 92] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_AVP_UNSUPPORTED 5001 - - The peer received a message that contained an AVP that is not - recognized or supported and was marked with the 'M' (Mandatory) - bit. A Diameter message with this error MUST contain one or more - Failed-AVP AVPs containing the AVPs that caused the failure. - - DIAMETER_UNKNOWN_SESSION_ID 5002 - - The request contained an unknown Session-Id. - - DIAMETER_AUTHORIZATION_REJECTED 5003 - - A request was received for which the user could not be authorized. - This error could occur if the service requested is not permitted - to the user. - - DIAMETER_INVALID_AVP_VALUE 5004 - - The request contained an AVP with an invalid value in its data - portion. A Diameter message indicating this error MUST include - the offending AVPs within a Failed-AVP AVP. - - DIAMETER_MISSING_AVP 5005 - - The request did not contain an AVP that is required by the Command - Code definition. If this value is sent in the Result-Code AVP, a - Failed-AVP AVP SHOULD be included in the message. The Failed-AVP - AVP MUST contain an example of the missing AVP complete with the - Vendor-Id if applicable. The value field of the missing AVP - should be of correct minimum length and contain zeroes. - - DIAMETER_RESOURCES_EXCEEDED 5006 - - A request was received that cannot be authorized because the user - has already expended allowed resources. An example of this error - condition is when a user that is restricted to one dial-up PPP - port attempts to establish a second PPP connection. - - DIAMETER_CONTRADICTING_AVPS 5007 - - The Home Diameter server has detected AVPs in the request that - contradicted each other, and it is not willing to provide service - to the user. The Failed-AVP AVP MUST be present, which contain - the AVPs that contradicted each other. - - - - - - -Fajardo, et al. Standards Track [Page 93] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_AVP_NOT_ALLOWED 5008 - - A message was received with an AVP that MUST NOT be present. The - Failed-AVP AVP MUST be included and contain a copy of the - offending AVP. - - DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009 - - A message was received that included an AVP that appeared more - often than permitted in the message definition. The Failed-AVP - AVP MUST be included and contain a copy of the first instance of - the offending AVP that exceeded the maximum number of occurrences. - - DIAMETER_NO_COMMON_APPLICATION 5010 - - This error is returned by a Diameter node that receives a CER - whereby no applications are common between the CER sending peer - and the CER receiving peer. - - DIAMETER_UNSUPPORTED_VERSION 5011 - - This error is returned when a request was received, whose version - number is unsupported. - - DIAMETER_UNABLE_TO_COMPLY 5012 - - This error is returned when a request is rejected for unspecified - reasons. - - DIAMETER_INVALID_BIT_IN_HEADER 5013 - - This error is returned when a reserved bit in the Diameter header - is set to one (1) or the bits in the Diameter header are set - incorrectly. - - DIAMETER_INVALID_AVP_LENGTH 5014 - - The request contained an AVP with an invalid length. A Diameter - message indicating this error MUST include the offending AVPs - within a Failed-AVP AVP. In cases where the erroneous AVP length - value exceeds the message length or is less than the minimum AVP - header length, it is sufficient to include the offending AVP - header and a zero filled payload of the minimum required length - for the payloads data type. If the AVP is a Grouped AVP, the - Grouped AVP header with an empty payload would be sufficient to - indicate the offending AVP. In the case where the offending AVP - header cannot be fully decoded when the AVP length is less than - - - - -Fajardo, et al. Standards Track [Page 94] - -RFC 6733 Diameter Base Protocol October 2012 - - - the minimum AVP header length, it is sufficient to include an - offending AVP header that is formulated by padding the incomplete - AVP header with zero up to the minimum AVP header length. - - DIAMETER_INVALID_MESSAGE_LENGTH 5015 - - This error is returned when a request is received with an invalid - message length. - - DIAMETER_INVALID_AVP_BIT_COMBO 5016 - - The request contained an AVP with which is not allowed to have the - given value in the AVP Flags field. A Diameter message indicating - this error MUST include the offending AVPs within a Failed-AVP - AVP. - - DIAMETER_NO_COMMON_SECURITY 5017 - - This error is returned when a CER message is received, and there - are no common security mechanisms supported between the peers. A - Capabilities-Exchange-Answer (CEA) message MUST be returned with - the Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY. - -7.2. Error Bit - - The 'E' (Error Bit) in the Diameter header is set when the request - caused a protocol-related error (see Section 7.1.3). A message with - the 'E' bit MUST NOT be sent as a response to an answer message. - Note that a message with the 'E' bit set is still subjected to the - processing rules defined in Section 6.2. When set, the answer - message will not conform to the CCF specification for the command; - instead, it and will conform to the following CCF: - - Message Format - - <answer-message> ::= < Diameter Header: code, ERR [, PXY] > - 0*1< Session-Id > - { Origin-Host } - { Origin-Realm } - { Result-Code } - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Experimental-Result ] - * [ Proxy-Info ] - * [ AVP ] - - - - -Fajardo, et al. Standards Track [Page 95] - -RFC 6733 Diameter Base Protocol October 2012 - - - Note that the code used in the header is the same than the one found - in the request message, but with the 'R' bit cleared and the 'E' bit - set. The 'P' bit in the header is set to the same value as the one - found in the request message. - -7.3. Error-Message AVP - - The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY - accompany a Result-Code AVP as a human-readable error message. The - Error-Message AVP is not intended to be useful in an environment - where error messages are processed automatically. It SHOULD NOT be - expected that the content of this AVP be parsed by network entities. - -7.4. Error-Reporting-Host AVP - - The Error-Reporting-Host AVP (AVP Code 294) is of type - DiameterIdentity. This AVP contains the identity of the Diameter - host that sent the Result-Code AVP to a value other than 2001 - (Success), only if the host setting the Result-Code is different from - the one encoded in the Origin-Host AVP. This AVP is intended to be - used for troubleshooting purposes, and it MUST be set when the - Result-Code AVP indicates a failure. - -7.5. Failed-AVP AVP - - The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides - debugging information in cases where a request is rejected or not - fully processed due to erroneous information in a specific AVP. The - value of the Result-Code AVP will provide information on the reason - for the Failed-AVP AVP. A Diameter answer message SHOULD contain an - instance of the Failed-AVP AVP that corresponds to the error - indicated by the Result-Code AVP. For practical purposes, this - Failed-AVP would typically refer to the first AVP processing error - that a Diameter node encounters. - - The possible reasons for this AVP are the presence of an improperly - constructed AVP, an unsupported or unrecognized AVP, an invalid AVP - value, the omission of a required AVP, the presence of an explicitly - excluded AVP (see tables in Section 10) or the presence of two or - more occurrences of an AVP that is restricted to 0, 1, or 0-1 - occurrences. - - A Diameter message SHOULD contain one Failed-AVP AVP, containing the - entire AVP that could not be processed successfully. If the failure - reason is omission of a required AVP, an AVP with the missing AVP - code, the missing Vendor-Id, and a zero-filled payload of the minimum - required length for the omitted AVP will be added. If the failure - reason is an invalid AVP length where the reported length is less - - - -Fajardo, et al. Standards Track [Page 96] - -RFC 6733 Diameter Base Protocol October 2012 - - - than the minimum AVP header length or greater than the reported - message length, a copy of the offending AVP header and a zero-filled - payload of the minimum required length SHOULD be added. - - In the case where the offending AVP is embedded within a Grouped AVP, - the Failed-AVP MAY contain the grouped AVP, which in turn contains - the single offending AVP. The same method MAY be employed if the - grouped AVP itself is embedded in yet another grouped AVP and so on. - In this case, the Failed-AVP MAY contain the grouped AVP hierarchy up - to the single offending AVP. This enables the recipient to detect - the location of the offending AVP when embedded in a group. - - AVP Format - - <Failed-AVP> ::= < AVP Header: 279 > - 1* {AVP} - -7.6. Experimental-Result AVP - - The Experimental-Result AVP (AVP Code 297) is of type Grouped, and - indicates whether a particular vendor-specific request was completed - successfully or whether an error occurred. This AVP has the - following structure: - - AVP Format - - Experimental-Result ::= < AVP Header: 297 > - { Vendor-Id } - { Experimental-Result-Code } - - The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies - the vendor responsible for the assignment of the result code that - follows. All Diameter answer messages defined in vendor-specific - applications MUST include either one Result-Code AVP or one - Experimental-Result AVP. - -7.7. Experimental-Result-Code AVP - - The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32 - and contains a vendor-assigned value representing the result of - processing the request. - - It is recommended that vendor-specific result codes follow the same - conventions given for the Result-Code AVP regarding the different - types of result codes and the handling of errors (for non-2xxx - values). - - - - - -Fajardo, et al. Standards Track [Page 97] - -RFC 6733 Diameter Base Protocol October 2012 - - -8. Diameter User Sessions - - In general, Diameter can provide two different types of services to - applications. The first involves authentication and authorization, - and it can optionally make use of accounting. The second only makes - use of accounting. - - When a service makes use of the authentication and/or authorization - portion of an application, and a user requests access to the network, - the Diameter client issues an auth request to its local server. The - auth request is defined in a service-specific Diameter application - (e.g., NASREQ). The request contains a Session-Id AVP, which is used - in subsequent messages (e.g., subsequent authorization, accounting, - etc.) relating to the user's session. The Session-Id AVP is a means - for the client and servers to correlate a Diameter message with a - user session. - - When a Diameter server authorizes a user to implement network - resources for a finite amount of time, and it is willing to extend - the authorization via a future request, it MUST add the - Authorization- Lifetime AVP to the answer message. The - Authorization-Lifetime AVP defines the maximum number of seconds a - user MAY make use of the resources before another authorization - request is expected by the server. The Auth-Grace-Period AVP - contains the number of seconds following the expiration of the - Authorization-Lifetime, after which the server will release all state - information related to the user's session. Note that if payment for - services is expected by the serving realm from the user's home realm, - the Authorization-Lifetime AVP, combined with the Auth-Grace-Period - AVP, implies the maximum length of the session for which the home - realm is willing to be fiscally responsible. Services provided past - the expiration of the Authorization-Lifetime and Auth-Grace-Period - AVPs are the responsibility of the access device. Of course, the - actual cost of services rendered is clearly outside the scope of the - protocol. - - An access device that does not expect to send a re-authorization or a - session termination request to the server MAY include the Auth- - Session-State AVP with the value set to NO_STATE_MAINTAINED as a hint - to the server. If the server accepts the hint, it agrees that since - no session termination message will be received once service to the - user is terminated, it cannot maintain state for the session. If the - answer message from the server contains a different value in the - Auth-Session-State AVP (or the default value if the AVP is absent), - the access device MUST follow the server's directives. Note that the - value NO_STATE_MAINTAINED MUST NOT be set in subsequent re- - authorization requests and answers. - - - - -Fajardo, et al. Standards Track [Page 98] - -RFC 6733 Diameter Base Protocol October 2012 - - - The base protocol does not include any authorization request - messages, since these are largely application-specific and are - defined in a Diameter application document. However, the base - protocol does define a set of messages that are used to terminate - user sessions. These are used to allow servers that maintain state - information to free resources. - - When a service only makes use of the accounting portion of the - Diameter protocol, even in combination with an application, the - Session-Id is still used to identify user sessions. However, the - session termination messages are not used, since a session is - signaled as being terminated by issuing an accounting stop message. - - Diameter may also be used for services that cannot be easily - categorized as authentication, authorization, or accounting (e.g., - certain Third Generation Partnership Project Internet Multimedia - System (3GPP IMS) interfaces). In such cases, the finite state - machine defined in subsequent sections may not be applicable. - Therefore, the application itself MAY need to define its own finite - state machine. However, such application-specific state machines - SHOULD follow the general state machine framework outlined in this - document such as the use of Session-Id AVPs and the use of STR/STA, - ASR/ASA messages for stateful sessions. - -8.1. Authorization Session State Machine - - This section contains a set of finite state machines, which represent - the life cycle of Diameter sessions and which MUST be observed by all - Diameter implementations that make use of the authentication and/or - authorization portion of a Diameter application. The term "Service- - Specific" below refers to a message defined in a Diameter application - (e.g., Mobile IPv4, NASREQ). - - There are four different authorization session state machines - supported in the Diameter base protocol. The first two describe a - session in which the server is maintaining session state, indicated - by the value of the Auth-Session-State AVP (or its absence). One - describes the session from a client perspective, the other from a - server perspective. The second two state machines are used when the - server does not maintain session state. Here again, one describes - the session from a client perspective, the other from a server - perspective. - - When a session is moved to the Idle state, any resources that were - allocated for the particular session must be released. Any event not - listed in the state machines MUST be considered an error condition, - and an answer, if applicable, MUST be returned to the originator of - the message. - - - -Fajardo, et al. Standards Track [Page 99] - -RFC 6733 Diameter Base Protocol October 2012 - - - In the case that an application does not support re-auth, the state - transitions related to server-initiated re-auth, when both client and - server sessions maintain state (e.g., Send RAR, Pending, Receive - RAA), MAY be ignored. - - In the state table, the event "Failure to send X" means that the - Diameter agent is unable to send command X to the desired - destination. This could be due to the peer being down or due to the - peer sending back a transient failure or temporary protocol error - notification DIAMETER_TOO_BUSY or DIAMETER_LOOP_DETECTED in the - Result-Code AVP of the corresponding Answer command. The event 'X - successfully sent' is the complement of 'Failure to send X'. - - The following state machine is observed by a client when state is - maintained on the server: - - CLIENT, STATEFUL - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send Pending - access service- - specific - auth req - - Idle ASR Received Send ASA Idle - for unknown session with - Result-Code = - UNKNOWN_ - SESSION_ID - - Idle RAR Received Send RAA Idle - for unknown session with - Result-Code = - UNKNOWN_ - SESSION_ID - - Pending Successful service-specific Grant Open - authorization answer Access - received with default - Auth-Session-State value - - Pending Successful service-specific Sent STR Discon - authorization answer received, - but service not provided - - Pending Error processing successful Sent STR Discon - service-specific authorization - answer - - - -Fajardo, et al. Standards Track [Page 100] - -RFC 6733 Diameter Base Protocol October 2012 - - - Pending Failed service-specific Clean up Idle - authorization answer received - - Open User or client device Send Open - requests access to service service- - specific - auth req - - Open Successful service-specific Provide Open - authorization answer received service - - Open Failed service-specific Discon. Idle - authorization answer user/device - received. - - Open RAR received and client will Send RAA Open - perform subsequent re-auth with - Result-Code = - SUCCESS - - Open RAR received and client will Send RAA Idle - not perform subsequent with - re-auth Result-Code != - SUCCESS, - Discon. - user/device - - Open Session-Timeout expires on Send STR Discon - access device - - Open ASR received, Send ASA Discon - client will comply with - with request to end the Result-Code = - session = SUCCESS, - Send STR. - - Open ASR Received, Send ASA Open - client will not comply with - with request to end the Result-Code != - session != SUCCESS - - Open Authorization-Lifetime + Send STR Discon - Auth-Grace-Period expires on - access device - - Discon ASR received Send ASA Discon - - - - - -Fajardo, et al. Standards Track [Page 101] - -RFC 6733 Diameter Base Protocol October 2012 - - - Discon STA received Discon. Idle - user/device - - The following state machine is observed by a server when it is - maintaining state for the session: - - SERVER, STATEFUL - State Event Action New State - --------------------------------------------------------------- - Idle Service-specific authorization Send Open - request received, and successful - user is authorized service- - specific - answer - - Idle Service-specific authorization Send Idle - request received, and failed - user is not authorized service- - specific - answer - - Open Service-specific authorization Send Open - request received, and user successful - is authorized service- - specific - answer - - Open Service-specific authorization Send Idle - request received, and user failed - is not authorized service- - specific - answer, - Clean up - - Open Home server wants to confirm Send RAR Pending - authentication and/or - authorization of the user - - Pending Received RAA with a failed Clean up Idle - Result-Code - - Pending Received RAA with Result-Code Update Open - = SUCCESS session - - Open Home server wants to Send ASR Discon - terminate the service - - - - - -Fajardo, et al. Standards Track [Page 102] - -RFC 6733 Diameter Base Protocol October 2012 - - - Open Authorization-Lifetime (and Clean up Idle - Auth-Grace-Period) expires - on home server - - Open Session-Timeout expires on Clean up Idle - home server - - Discon Failure to send ASR Wait, Discon - resend ASR - - Discon ASR successfully sent and Clean up Idle - ASA Received with Result-Code - - Not ASA Received None No Change - Discon - - Any STR Received Send STA, Idle - Clean up - - The following state machine is observed by a client when state is not - maintained on the server: - - CLIENT, STATELESS - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send Pending - access service- - specific - auth req - - Pending Successful service-specific Grant Open - authorization answer access - received with Auth-Session- - State set to - NO_STATE_MAINTAINED - - Pending Failed service-specific Clean up Idle - authorization answer - received - - Open Session-Timeout expires on Discon. Idle - access device user/device - - Open Service to user is terminated Discon. Idle - user/device - - - - - - -Fajardo, et al. Standards Track [Page 103] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following state machine is observed by a server when it is not - maintaining state for the session: - - SERVER, STATELESS - State Event Action New State - --------------------------------------------------------------- - Idle Service-specific authorization Send Idle - request received, and service- - successfully processed specific - answer - -8.2. Accounting Session State Machine - - The following state machines MUST be supported for applications that - have an accounting portion or that require only accounting services. - The first state machine is to be observed by clients. - - See Section 9.7 for Accounting Command Codes and Section 9.8 for - Accounting AVPs. - - The server side in the accounting state machine depends in some cases - on the particular application. The Diameter base protocol defines a - default state machine that MUST be followed by all applications that - have not specified other state machines. This is the second state - machine in this section described below. - - The default server side state machine requires the reception of - accounting records in any order and at any time, and it does not - place any standards requirement on the processing of these records. - Implementations of Diameter may perform checking, ordering, - correlation, fraud detection, and other tasks based on these records. - AVPs may need to be inspected as a part of these tasks. The tasks - can happen either immediately after record reception or in a post- - processing phase. However, as these tasks are typically application - or even policy dependent, they are not standardized by the Diameter - specifications. Applications MAY define requirements on when to - accept accounting records based on the used value of Accounting- - Realtime-Required AVP, credit-limit checks, and so on. - - However, the Diameter base protocol defines one optional server side - state machine that MAY be followed by applications that require - keeping track of the session state at the accounting server. Note - that such tracking is incompatible with the ability to sustain long - duration connectivity problems. Therefore, the use of this state - machine is recommended only in applications where the value of the - Accounting-Realtime-Required AVP is DELIVER_AND_GRANT; hence, - accounting connectivity problems are required to cause the serviced - user to be disconnected. Otherwise, records produced by the client - - - -Fajardo, et al. Standards Track [Page 104] - -RFC 6733 Diameter Base Protocol October 2012 - - - may be lost by the server, which no longer accepts them after the - connectivity is re-established. This state machine is the third - state machine in this section. The state machine is supervised by a - supervision session timer Ts, whose value should be reasonably higher - than the Acct_Interim_Interval value. Ts MAY be set to two times the - value of the Acct_Interim_Interval so as to avoid the accounting - session in the Diameter server to change to Idle state in case of - short transient network failure. - - Any event not listed in the state machines MUST be considered as an - error condition, and a corresponding answer, if applicable, MUST be - returned to the originator of the message. - - In the state table, the event "Failure to send" means that the - Diameter client is unable to communicate with the desired - destination. This could be due to the peer being down, or due to the - peer sending back a transient failure or temporary protocol error - notification DIAMETER_OUT_OF_SPACE, DIAMETER_TOO_BUSY, or - DIAMETER_LOOP_DETECTED in the Result-Code AVP of the Accounting - Answer command. - - The event "Failed answer" means that the Diameter client received a - non-transient failure notification in the Accounting Answer command. - - Note that the action "Disconnect user/dev" MUST also have an effect - on the authorization session state table, e.g., cause the STR message - to be sent, if the given application has both authentication/ - authorization and accounting portions. - - The states PendingS, PendingI, PendingL, PendingE, and PendingB stand - for pending states to wait for an answer to an accounting request - related to a Start, Interim, Stop, Event, or buffered record, - respectively. - - CLIENT, ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send PendingS - access accounting - start req. - - Idle Client or device requests Send PendingE - a one-time service accounting - event req - - Idle Records in storage Send PendingB - record - - - - -Fajardo, et al. Standards Track [Page 105] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingS Successful accounting Open - start answer received - - PendingS Failure to send and buffer Store Open - space available and real time Start - not equal to DELIVER_AND_GRANT Record - - PendingS Failure to send and no buffer Open - space available and real time - equal to GRANT_AND_LOSE - - PendingS Failure to send and no Disconnect Idle - buffer space available and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingS Failed accounting start answer Open - received and real time equal - to GRANT_AND_LOSE - - PendingS Failed accounting start answer Disconnect Idle - received and real time not user/dev - equal to GRANT_AND_LOSE - - PendingS User service terminated Store PendingS - stop - record - - Open Interim interval elapses Send PendingI - accounting - interim - record - - Open User service terminated Send PendingL - accounting - stop req. - - PendingI Successful accounting interim Open - answer received - - PendingI Failure to send and (buffer Store Open - space available or old interim - record can be overwritten) record - and real time not equal to - DELIVER_AND_GRANT - - - - - - -Fajardo, et al. Standards Track [Page 106] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingI Failure to send and no buffer Open - space available and real time - equal to GRANT_AND_LOSE - - PendingI Failure to send and no Disconnect Idle - buffer space available and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingI Failed accounting interim Open - answer received and real time - equal to GRANT_AND_LOSE - - PendingI Failed accounting interim Disconnect Idle - answer received and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingI User service terminated Store PendingI - stop - record - PendingE Successful accounting Idle - event answer received - - PendingE Failure to send and buffer Store Idle - space available event - record - - PendingE Failure to send and no buffer Idle - space available - - PendingE Failed accounting event answer Idle - received - - PendingB Successful accounting answer Delete Idle - received record - - PendingB Failure to send Idle - - PendingB Failed accounting answer Delete Idle - received record - - PendingL Successful accounting Idle - stop answer received - - PendingL Failure to send and buffer Store Idle - space available stop - record - - - -Fajardo, et al. Standards Track [Page 107] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingL Failure to send and no buffer Idle - space available - - PendingL Failed accounting stop answer Idle - received - - - SERVER, STATELESS ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - - Idle Accounting start request Send Idle - received and successfully accounting - processed. start - answer - - Idle Accounting event request Send Idle - received and successfully accounting - processed. event - answer - - Idle Interim record received Send Idle - and successfully processed. accounting - interim - answer - - Idle Accounting stop request Send Idle - received and successfully accounting - processed stop answer - - Idle Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 108] - -RFC 6733 Diameter Base Protocol October 2012 - - - SERVER, STATEFUL ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - - Idle Accounting start request Send Open - received and successfully accounting - processed. start - answer; - Start Ts - - Idle Accounting event request Send Idle - received and successfully accounting - processed. event - answer - Idle Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE - - Open Interim record received Send Open - and successfully processed. accounting - interim - answer; - Restart Ts - - Open Accounting stop request Send Idle - received and successfully accounting - processed stop answer; - Stop Ts - - Open Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE; - Stop Ts - - Open Session supervision timer Ts Stop Ts Idle - expired - - - - - - - - - -Fajardo, et al. Standards Track [Page 109] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.3. Server-Initiated Re-Auth - - A Diameter server may initiate a re-authentication and/or re- - authorization service for a particular session by issuing a Re-Auth- - Request (RAR). - - For example, for prepaid services, the Diameter server that - originally authorized a session may need some confirmation that the - user is still using the services. - - An access device that receives an RAR message with the Session-Id - equal to a currently active session MUST initiate a re-auth towards - the user, if the service supports this particular feature. Each - Diameter application MUST state whether server-initiated re-auth is - supported, since some applications do not allow access devices to - prompt the user for re-auth. - -8.3.1. Re-Auth-Request - - The Re-Auth-Request (RAR), indicated by the Command Code set to 258 - and the message flags' 'R' bit set, may be sent by any server to the - access device that is providing session service, to request that the - user be re-authenticated and/or re-authorized. - - - Message Format - - <RAR> ::= < Diameter Header: 258, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Destination-Host } - { Auth-Application-Id } - { Re-Auth-Request-Type } - [ User-Name ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -8.3.2. Re-Auth-Answer - - The Re-Auth-Answer (RAA), indicated by the Command Code set to 258 - and the message flags' 'R' bit clear, is sent in response to the RAR. - The Result-Code AVP MUST be present, and it indicates the disposition - of the request. - - - - -Fajardo, et al. Standards Track [Page 110] - -RFC 6733 Diameter Base Protocol October 2012 - - - A successful RAA message MUST be followed by an application-specific - authentication and/or authorization message. - - Message Format - - <RAA> ::= < Diameter Header: 258, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.4. Session Termination - - It is necessary for a Diameter server that authorized a session, for - which it is maintaining state, to be notified when that session is no - longer active, both for tracking purposes as well as to allow - stateful agents to release any resources that they may have provided - for the user's session. For sessions whose state is not being - maintained, this section is not used. - - When a user session that required Diameter authorization terminates, - the access device that provided the service MUST issue a Session- - Termination-Request (STR) message to the Diameter server that - authorized the service, to notify it that the session is no longer - active. An STR MUST be issued when a user session terminates for any - reason, including user logoff, expiration of Session-Timeout, - administrative action, termination upon receipt of an Abort-Session- - Request (see below), orderly shutdown of the access device, etc. - - The access device also MUST issue an STR for a session that was - authorized but never actually started. This could occur, for - example, due to a sudden resource shortage in the access device, or - because the access device is unwilling to provide the type of service - requested in the authorization, or because the access device does not - support a mandatory AVP returned in the authorization, etc. - - It is also possible that a session that was authorized is never - actually started due to action of a proxy. For example, a proxy may - - - -Fajardo, et al. Standards Track [Page 111] - -RFC 6733 Diameter Base Protocol October 2012 - - - modify an authorization answer, converting the result from success to - failure, prior to forwarding the message to the access device. If - the answer did not contain an Auth-Session-State AVP with the value - NO_STATE_MAINTAINED, a proxy that causes an authorized session not to - be started MUST issue an STR to the Diameter server that authorized - the session, since the access device has no way of knowing that the - session had been authorized. - - A Diameter server that receives an STR message MUST clean up - resources (e.g., session state) associated with the Session-Id - specified in the STR and return a Session-Termination-Answer. - - A Diameter server also MUST clean up resources when the Session- - Timeout expires, or when the Authorization-Lifetime and the Auth- - Grace-Period AVPs expire without receipt of a re-authorization - request, regardless of whether an STR for that session is received. - The access device is not expected to provide service beyond the - expiration of these timers; thus, expiration of either of these - timers implies that the access device may have unexpectedly shut - down. - -8.4.1. Session-Termination-Request - - The Session-Termination-Request (STR), indicated by the Command Code - set to 275 and the Command Flags' 'R' bit set, is sent by a Diameter - client or by a Diameter proxy to inform the Diameter server that an - authenticated and/or authorized session is being terminated. - - Message Format - - <STR> ::= < Diameter Header: 275, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Auth-Application-Id } - { Termination-Cause } - [ User-Name ] - [ Destination-Host ] - * [ Class ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - - - - - - - -Fajardo, et al. Standards Track [Page 112] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.4.2. Session-Termination-Answer - - The Session-Termination-Answer (STA), indicated by the Command Code - set to 275 and the message flags' 'R' bit clear, is sent by the - Diameter server to acknowledge the notification that the session has - been terminated. The Result-Code AVP MUST be present, and it MAY - contain an indication that an error occurred while servicing the STR. - - Upon sending or receipt of the STA, the Diameter server MUST release - all resources for the session indicated by the Session-Id AVP. Any - intermediate server in the Proxy-Chain MAY also release any - resources, if necessary. - - Message Format - - <STA> ::= < Diameter Header: 275, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - * [ Class ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Origin-State-Id ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.5. Aborting a Session - - A Diameter server may request that the access device stop providing - service for a particular session by issuing an Abort-Session-Request - (ASR). - - For example, the Diameter server that originally authorized the - session may be required to cause that session to be stopped for lack - of credit or other reasons that were not anticipated when the session - was first authorized. - - An access device that receives an ASR with Session-ID equal to a - currently active session MAY stop the session. Whether the access - device stops the session or not is implementation and/or - configuration dependent. For example, an access device may honor - ASRs from certain agents only. In any case, the access device MUST - - - -Fajardo, et al. Standards Track [Page 113] - -RFC 6733 Diameter Base Protocol October 2012 - - - respond with an Abort-Session-Answer, including a Result-Code AVP to - indicate what action it took. - -8.5.1. Abort-Session-Request - - The Abort-Session-Request (ASR), indicated by the Command Code set to - 274 and the message flags' 'R' bit set, may be sent by any Diameter - server or any Diameter proxy to the access device that is providing - session service, to request that the session identified by the - Session-Id be stopped. - - Message Format - - <ASR> ::= < Diameter Header: 274, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Destination-Host } - { Auth-Application-Id } - [ User-Name ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -8.5.2. Abort-Session-Answer - - The Abort-Session-Answer (ASA), indicated by the Command Code set to - 274 and the message flags' 'R' bit clear, is sent in response to the - ASR. The Result-Code AVP MUST be present and indicates the - disposition of the request. - - If the session identified by Session-Id in the ASR was successfully - terminated, the Result-Code is set to DIAMETER_SUCCESS. If the - session is not currently active, the Result-Code is set to - DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the - session for any other reason, the Result-Code is set to - DIAMETER_UNABLE_TO_COMPLY. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 114] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ASA> ::= < Diameter Header: 274, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.6. Inferring Session Termination from Origin-State-Id - - The Origin-State-Id is used to allow detection of terminated sessions - for which no STR would have been issued, due to unanticipated - shutdown of an access device. - - A Diameter client or access device increments the value of the - Origin-State-Id every time it is started or powered up. The new - Origin-State-Id is then sent in the CER/CEA message immediately upon - connection to the server. The Diameter server receiving the new - Origin-State-Id can determine whether the sending Diameter client had - abruptly shut down by comparing the old value of the Origin-State-Id - it has kept for that specific client is less than the new value and - whether it has un-terminated sessions originating from that client. - - An access device can also include the Origin-State-Id in request - messages other than the CER if there are relays or proxies in between - the access device and the server. In this case, however, the server - cannot discover that the access device has been restarted unless and - until it receives a new request from it. Therefore, this mechanism - is more opportunistic across proxies and relays. - - The Diameter server may assume that all sessions that were active - prior to detection of a client restart have been terminated. The - Diameter server MAY clean up all session state associated with such - lost sessions, and it MAY also issue STRs for all such lost sessions - that were authorized on upstream servers, to allow session state to - be cleaned up globally. - - - - - -Fajardo, et al. Standards Track [Page 115] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.7. Auth-Request-Type AVP - - The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is - included in application-specific auth requests to inform the peers - whether a user is to be authenticated only, authorized only, or both. - Note any value other than both MAY cause RADIUS interoperability - issues. The following values are defined: - - AUTHENTICATE_ONLY 1 - - The request being sent is for authentication only, and it MUST - contain the relevant application-specific authentication AVPs that - are needed by the Diameter server to authenticate the user. - - AUTHORIZE_ONLY 2 - - The request being sent is for authorization only, and it MUST - contain the application-specific authorization AVPs that are - necessary to identify the service being requested/offered. - - AUTHORIZE_AUTHENTICATE 3 - - The request contains a request for both authentication and - authorization. The request MUST include both the relevant - application-specific authentication information and authorization - information necessary to identify the service being requested/ - offered. - -8.8. Session-Id AVP - - The Session-Id AVP (AVP Code 263) is of type UTF8String and is used - to identify a specific session (see Section 8). All messages - pertaining to a specific session MUST include only one Session-Id - AVP, and the same value MUST be used throughout the life of a - session. When present, the Session-Id SHOULD appear immediately - following the Diameter header (see Section 3). - - The Session-Id MUST be globally and eternally unique, as it is meant - to uniquely identify a user session without reference to any other - information, and it may be needed to correlate historical - authentication information with accounting information. The - Session-Id includes a mandatory portion and an implementation-defined - portion; a recommended format for the implementation-defined portion - is outlined below. - - The Session-Id MUST begin with the sender's identity encoded in the - DiameterIdentity type (see Section 4.3.1). The remainder of the - Session-Id is delimited by a ";" character, and it MAY be any - - - -Fajardo, et al. Standards Track [Page 116] - -RFC 6733 Diameter Base Protocol October 2012 - - - sequence that the client can guarantee to be eternally unique; - however, the following format is recommended, (square brackets [] - indicate an optional element): - - <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>] - - <high 32 bits> and <low 32 bits> are decimal representations of the - high and low 32 bits of a monotonically increasing 64-bit value. The - 64-bit value is rendered in two part to simplify formatting by 32-bit - processors. At startup, the high 32 bits of the 64-bit value MAY be - initialized to the time in NTP format [RFC5905], and the low 32 bits - MAY be initialized to zero. This will for practical purposes - eliminate the possibility of overlapping Session-Ids after a reboot, - assuming the reboot process takes longer than a second. - Alternatively, an implementation MAY keep track of the increasing - value in non-volatile memory. - - - <optional value> is implementation specific, but it may include a - modem's device Id, a Layer 2 address, timestamp, etc. - - Example, in which there is no optional value: - - accesspoint7.example.com;1876543210;523 - - Example, in which there is an optional value: - - accesspoint7.example.com;1876543210;523;[email protected] - - The Session-Id is created by the Diameter application initiating the - session, which, in most cases, is done by the client. Note that a - Session-Id MAY be used for both the authentication, authorization, - and accounting commands of a given application. - -8.9. Authorization-Lifetime AVP - - The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32 - and contains the maximum number of seconds of service to be provided - to the user before the user is to be re-authenticated and/or re- - authorized. Care should be taken when the Authorization-Lifetime - value is determined, since a low, non-zero value could create - significant Diameter traffic, which could congest both the network - and the agents. - - A value of zero (0) means that immediate re-auth is necessary by the - access device. The absence of this AVP, or a value of all ones - (meaning all bits in the 32-bit field are set to one) means no re- - auth is expected. - - - -Fajardo, et al. Standards Track [Page 117] - -RFC 6733 Diameter Base Protocol October 2012 - - - If both this AVP and the Session-Timeout AVP are present in a - message, the value of the latter MUST NOT be smaller than the - Authorization-Lifetime AVP. - - An Authorization-Lifetime AVP MAY be present in re-authorization - messages, and it contains the number of seconds the user is - authorized to receive service from the time the re-auth answer - message is received by the access device. - - This AVP MAY be provided by the client as a hint of the maximum - lifetime that it is willing to accept. The server MUST return a - value that is equal to, or smaller than, the one provided by the - client. - -8.10. Auth-Grace-Period AVP - - The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and - contains the number of seconds the Diameter server will wait - following the expiration of the Authorization-Lifetime AVP before - cleaning up resources for the session. - -8.11. Auth-Session-State AVP - - The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and - specifies whether state is maintained for a particular session. The - client MAY include this AVP in requests as a hint to the server, but - the value in the server's answer message is binding. The following - values are supported: - - STATE_MAINTAINED 0 - - This value is used to specify that session state is being - maintained, and the access device MUST issue a session termination - message when service to the user is terminated. This is the - default value. - - NO_STATE_MAINTAINED 1 - - This value is used to specify that no session termination messages - will be sent by the access device upon expiration of the - Authorization-Lifetime. - -8.12. Re-Auth-Request-Type AVP - - The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and - is included in application-specific auth answers to inform the client - of the action expected upon expiration of the Authorization-Lifetime. - - - - -Fajardo, et al. Standards Track [Page 118] - -RFC 6733 Diameter Base Protocol October 2012 - - - If the answer message contains an Authorization-Lifetime AVP with a - positive value, the Re-Auth-Request-Type AVP MUST be present in an - answer message. The following values are defined: - - AUTHORIZE_ONLY 0 - - An authorization only re-auth is expected upon expiration of the - Authorization-Lifetime. This is the default value if the AVP is - not present in answer messages that include the Authorization- - Lifetime. - - AUTHORIZE_AUTHENTICATE 1 - - An authentication and authorization re-auth is expected upon - expiration of the Authorization-Lifetime. - -8.13. Session-Timeout AVP - - The Session-Timeout AVP (AVP Code 27) [RFC2865] is of type Unsigned32 - and contains the maximum number of seconds of service to be provided - to the user before termination of the session. When both the - Session-Timeout and the Authorization-Lifetime AVPs are present in an - answer message, the former MUST be equal to or greater than the value - of the latter. - - A session that terminates on an access device due to the expiration - of the Session-Timeout MUST cause an STR to be issued, unless both - the access device and the home server had previously agreed that no - session termination messages would be sent (see Section 8). - - A Session-Timeout AVP MAY be present in a re-authorization answer - message, and it contains the remaining number of seconds from the - beginning of the re-auth. - - A value of zero, or the absence of this AVP, means that this session - has an unlimited number of seconds before termination. - - This AVP MAY be provided by the client as a hint of the maximum - timeout that it is willing to accept. However, the server MAY return - a value that is equal to, or smaller than, the one provided by the - client. - -8.14. User-Name AVP - - The User-Name AVP (AVP Code 1) [RFC2865] is of type UTF8String, which - contains the User-Name, in a format consistent with the NAI - specification [RFC4282]. - - - - -Fajardo, et al. Standards Track [Page 119] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.15. Termination-Cause AVP - - The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and - is used to indicate the reason why a session was terminated on the - access device. The currently assigned values for this AVP can be - found in the IANA registry for Termination-Cause AVP Values - [IANATCV]. - -8.16. Origin-State-Id AVP - - The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a - monotonically increasing value that is advanced whenever a Diameter - entity restarts with loss of previous state, for example, upon - reboot. Origin-State-Id MAY be included in any Diameter message, - including CER. - - A Diameter entity issuing this AVP MUST create a higher value for - this AVP each time its state is reset. A Diameter entity MAY set - Origin-State-Id to the time of startup, or it MAY use an incrementing - counter retained in non-volatile memory across restarts. - - The Origin-State-Id, if present, MUST reflect the state of the entity - indicated by Origin-Host. If a proxy modifies Origin-Host, it MUST - either remove Origin-State-Id or modify it appropriately as well. - Typically, Origin-State-Id is used by an access device that always - starts up with no active sessions; that is, any session active prior - to restart will have been lost. By including Origin-State-Id in a - message, it allows other Diameter entities to infer that sessions - associated with a lower Origin-State-Id are no longer active. If an - access device does not intend for such inferences to be made, it MUST - either not include Origin-State-Id in any message or set its value to - 0. - -8.17. Session-Binding AVP - - The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and it - MAY be present in application-specific authorization answer messages. - If present, this AVP MAY inform the Diameter client that all future - application-specific re-auth and Session-Termination-Request messages - for this session MUST be sent to the same authorization server. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 120] - -RFC 6733 Diameter Base Protocol October 2012 - - - This field is a bit mask, and the following bits have been defined: - - RE_AUTH 1 - - When set, future re-auth messages for this session MUST NOT - include the Destination-Host AVP. When cleared, the default - value, the Destination-Host AVP MUST be present in all re-auth - messages for this session. - - STR 2 - - When set, the STR message for this session MUST NOT include the - Destination-Host AVP. When cleared, the default value, the - Destination-Host AVP MUST be present in the STR message for this - session. - - ACCOUNTING 4 - - When set, all accounting messages for this session MUST NOT - include the Destination-Host AVP. When cleared, the default - value, the Destination-Host AVP, if known, MUST be present in all - accounting messages for this session. - -8.18. Session-Server-Failover AVP - - The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated - and MAY be present in application-specific authorization answer - messages that either do not include the Session-Binding AVP or - include the Session-Binding AVP with any of the bits set to a zero - value. If present, this AVP MAY inform the Diameter client that if a - re-auth or STR message fails due to a delivery problem, the Diameter - client SHOULD issue a subsequent message without the Destination-Host - AVP. When absent, the default value is REFUSE_SERVICE. - - The following values are supported: - - REFUSE_SERVICE 0 - - If either the re-auth or the STR message delivery fails, terminate - service with the user and do not attempt any subsequent attempts. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 121] - -RFC 6733 Diameter Base Protocol October 2012 - - - TRY_AGAIN 1 - - If either the re-auth or the STR message delivery fails, resend - the failed message without the Destination-Host AVP present. - - ALLOW_SERVICE 2 - - If re-auth message delivery fails, assume that re-authorization - succeeded. If STR message delivery fails, terminate the session. - - TRY_AGAIN_ALLOW_SERVICE 3 - - If either the re-auth or the STR message delivery fails, resend - the failed message without the Destination-Host AVP present. If - the second delivery fails for re-auth, assume re-authorization - succeeded. If the second delivery fails for STR, terminate the - session. - -8.19. Multi-Round-Time-Out AVP - - The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32 and - SHOULD be present in application-specific authorization answer - messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH. - This AVP contains the maximum number of seconds that the access - device MUST provide the user in responding to an authentication - request. - -8.20. Class AVP - - The Class AVP (AVP Code 25) is of type OctetString and is used by - Diameter servers to return state information to the access device. - When one or more Class AVPs are present in application-specific - authorization answer messages, they MUST be present in subsequent re- - authorization, session termination and accounting messages. Class - AVPs found in a re-authorization answer message override the ones - found in any previous authorization answer message. Diameter server - implementations SHOULD NOT return Class AVPs that require more than - 4096 bytes of storage on the Diameter client. A Diameter client that - receives Class AVPs whose size exceeds local available storage MUST - terminate the session. - -8.21. Event-Timestamp AVP - - The Event-Timestamp (AVP Code 55) is of type Time and MAY be included - in an Accounting-Request and Accounting-Answer messages to record the - time that the reported event occurred, in seconds since January 1, - 1900 00:00 UTC. - - - - -Fajardo, et al. Standards Track [Page 122] - -RFC 6733 Diameter Base Protocol October 2012 - - -9. Accounting - - This accounting protocol is based on a server directed model with - capabilities for real-time delivery of accounting information. - Several fault resilience methods [RFC2975] have been built into the - protocol in order minimize loss of accounting data in various fault - situations and under different assumptions about the capabilities of - the used devices. - -9.1. Server Directed Model - - The server directed model means that the device generating the - accounting data gets information from either the authorization server - (if contacted) or the accounting server regarding the way accounting - data shall be forwarded. This information includes accounting record - timeliness requirements. - - As discussed in [RFC2975], real-time transfer of accounting records - is a requirement, such as the need to perform credit-limit checks and - fraud detection. Note that batch accounting is not a requirement, - and is therefore not supported by Diameter. Should batched - accounting be required in the future, a new Diameter application will - need to be created, or it could be handled using another protocol. - Note, however, that even if at the Diameter layer, accounting - requests are processed one by one; transport protocols used under - Diameter typically batch several requests in the same packet under - heavy traffic conditions. This may be sufficient for many - applications. - - The authorization server (chain) directs the selection of proper - transfer strategy, based on its knowledge of the user and - relationships of roaming partnerships. The server (or agents) uses - the Acct-Interim-Interval and Accounting-Realtime-Required AVPs to - control the operation of the Diameter peer operating as a client. - The Acct-Interim-Interval AVP, when present, instructs the Diameter - node acting as a client to produce accounting records continuously - even during a session. Accounting-Realtime-Required AVP is used to - control the behavior of the client when the transfer of accounting - records from the Diameter client is delayed or unsuccessful. - - The Diameter accounting server MAY override the interim interval or - the real-time requirements by including the Acct-Interim-Interval or - Accounting-Realtime-Required AVP in the Accounting-Answer message. - When one of these AVPs is present, the latest value received SHOULD - be used in further accounting activities for the same session. - - - - - - -Fajardo, et al. Standards Track [Page 123] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.2. Protocol Messages - - A Diameter node that receives a successful authentication and/or - authorization message from the Diameter server SHOULD collect - accounting information for the session. The Accounting-Request - message is used to transmit the accounting information to the - Diameter server, which MUST reply with the Accounting-Answer message - to confirm reception. The Accounting-Answer message includes the - Result-Code AVP, which MAY indicate that an error was present in the - accounting message. The value of the Accounting-Realtime-Required - AVP received earlier for the session in question may indicate that - the user's session has to be terminated when a rejected Accounting- - Request message was received. - -9.3. Accounting Application Extension and Requirements - - Each Diameter application (e.g., NASREQ, Mobile IP) SHOULD define its - service-specific AVPs that MUST be present in the Accounting-Request - message in a section titled "Accounting AVPs". The application MUST - assume that the AVPs described in this document will be present in - all Accounting messages, so only their respective service-specific - AVPs need to be defined in that section. - - Applications have the option of using one or both of the following - accounting application extension models: - - Split Accounting Service - - The accounting message will carry the Application Id of the - Diameter base accounting application (see Section 2.4). - Accounting messages may be routed to Diameter nodes other than the - corresponding Diameter application. These nodes might be - centralized accounting servers that provide accounting service for - multiple different Diameter applications. These nodes MUST - advertise the Diameter base accounting Application Id during - capabilities exchange. - - Coupled Accounting Service - - The accounting message will carry the Application Id of the - application that is using it. The application itself will process - the received accounting records or forward them to an accounting - server. There is no accounting application advertisement required - during capabilities exchange, and the accounting messages will be - routed the same way as any of the other application messages. - - In cases where an application does not define its own accounting - service, it is preferred that the split accounting model be used. - - - -Fajardo, et al. Standards Track [Page 124] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.4. Fault Resilience - - Diameter base protocol mechanisms are used to overcome small message - loss and network faults of a temporary nature. - - Diameter peers acting as clients MUST implement the use of failover - to guard against server failures and certain network failures. - Diameter peers acting as agents or related off-line processing - systems MUST detect duplicate accounting records caused by the - sending of the same record to several servers and duplication of - messages in transit. This detection MUST be based on the inspection - of the Session-Id and Accounting-Record-Number AVP pairs. Appendix C - discusses duplicate detection needs and implementation issues. - - Diameter clients MAY have non-volatile memory for the safe storage of - accounting records over reboots or extended network failures, network - partitions, and server failures. If such memory is available, the - client SHOULD store new accounting records there as soon as the - records are created and until a positive acknowledgement of their - reception from the Diameter server has been received. Upon a reboot, - the client MUST start sending the records in the non-volatile memory - to the accounting server with the appropriate modifications in - termination cause, session length, and other relevant information in - the records. - - A further application of this protocol may include AVPs to control - the maximum number of accounting records that may be stored in the - Diameter client without committing them to the non-volatile memory or - transferring them to the Diameter server. - - The client SHOULD NOT remove the accounting data from any of its - memory areas before the correct Accounting-Answer has been received. - The client MAY remove the oldest, undelivered, or as yet - unacknowledged accounting data if it runs out of resources such as - memory. It is an implementation-dependent matter for the client to - accept new sessions under this condition. - -9.5. Accounting Records - - In all accounting records, the Session-Id AVP MUST be present; the - User-Name AVP MUST be present if it is available to the Diameter - client. - - Different types of accounting records are sent depending on the - actual type of accounted service and the authorization server's - directions for interim accounting. If the accounted service is a - - - - - -Fajardo, et al. Standards Track [Page 125] - -RFC 6733 Diameter Base Protocol October 2012 - - - one-time event, meaning that the start and stop of the event are - simultaneous, then the Accounting-Record-Type AVP MUST be present and - set to the value EVENT_RECORD. - - If the accounted service is of a measurable length, then the AVP MUST - use the values START_RECORD, STOP_RECORD, and possibly, - INTERIM_RECORD. If the authorization server has not directed interim - accounting to be enabled for the session, two accounting records MUST - be generated for each service of type session. When the initial - Accounting-Request for a given session is sent, the Accounting- - Record-Type AVP MUST be set to the value START_RECORD. When the last - Accounting-Request is sent, the value MUST be STOP_RECORD. - - If the authorization server has directed interim accounting to be - enabled, the Diameter client MUST produce additional records between - the START_RECORD and STOP_RECORD, marked INTERIM_RECORD. The - production of these records is directed by Acct-Interim-Interval as - well as any re-authentication or re-authorization of the session. - The Diameter client MUST overwrite any previous interim accounting - records that are locally stored for delivery, if a new record is - being generated for the same session. This ensures that only one - pending interim record can exist on an access device for any given - session. - - A particular value of Accounting-Sub-Session-Id MUST appear only in - one sequence of accounting records from a Diameter client, except for - the purposes of retransmission. The one sequence that is sent MUST - be either one record with Accounting-Record-Type AVP set to the value - EVENT_RECORD or several records starting with one having the value - START_RECORD, followed by zero or more INTERIM_RECORDs and a single - STOP_RECORD. A particular Diameter application specification MUST - define the type of sequences that MUST be used. - -9.6. Correlation of Accounting Records - - If an application uses accounting messages, it can correlate - accounting records with a specific application session by using the - Session-Id of the particular application session in the accounting - messages. Accounting messages MAY also use a different Session-Id - from that of the application sessions, in which case, other session- - related information is needed to perform correlation. - - In cases where an application requires multiple accounting sub- - sessions, an Accounting-Sub-Session-Id AVP is used to differentiate - each sub-session. The Session-Id would remain constant for all sub- - sessions and is used to correlate all the sub-sessions to a - particular application session. Note that receiving a STOP_RECORD - - - - -Fajardo, et al. Standards Track [Page 126] - -RFC 6733 Diameter Base Protocol October 2012 - - - with no Accounting-Sub-Session-Id AVP when sub-sessions were - originally used in the START_RECORD messages implies that all sub- - sessions are terminated. - - There are also cases where an application needs to correlate multiple - application sessions into a single accounting record; the accounting - record may span multiple different Diameter applications and sessions - used by the same user at a given time. In such cases, the Acct- - Multi-Session-Id AVP is used. The Acct-Multi-Session-Id AVP SHOULD - be signaled by the server to the access device (typically, during - authorization) when it determines that a request belongs to an - existing session. The access device MUST then include the Acct- - Multi-Session-Id AVP in all subsequent accounting messages. - - The Acct-Multi-Session-Id AVP MAY include the value of the original - Session-Id. Its contents are implementation specific, but the MUST - be globally unique across other Acct-Multi-Session-Ids and MUST NOT - change during the life of a session. - - A Diameter application document MUST define the exact concept of a - session that is being accounted, and it MAY define the concept of a - multi-session. For instance, the NASREQ DIAMETER application treats - a single PPP connection to a Network Access Server as one session and - a set of Multilink PPP sessions as one multi-session. - -9.7. Accounting Command Codes - - This section defines Command Code values that MUST be supported by - all Diameter implementations that provide accounting services. - -9.7.1. Accounting-Request - - The Accounting-Request (ACR) command, indicated by the Command Code - field set to 271 and the Command Flags' 'R' bit set, is sent by a - Diameter node, acting as a client, in order to exchange accounting - information with a peer. - - In addition to the AVPs listed below, Accounting-Request messages - SHOULD include service-specific accounting AVPs. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 127] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ACR> ::= < Diameter Header: 271, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Accounting-Record-Type } - { Accounting-Record-Number } - [ Acct-Application-Id ] - [ Vendor-Specific-Application-Id ] - [ User-Name ] - [ Destination-Host ] - [ Accounting-Sub-Session-Id ] - [ Acct-Session-Id ] - [ Acct-Multi-Session-Id ] - [ Acct-Interim-Interval ] - [ Accounting-Realtime-Required ] - [ Origin-State-Id ] - [ Event-Timestamp ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -9.7.2. Accounting-Answer - - The Accounting-Answer (ACA) command, indicated by the Command Code - field set to 271 and the Command Flags' 'R' bit cleared, is used to - acknowledge an Accounting-Request command. The Accounting-Answer - command contains the same Session-Id as the corresponding request. - - Only the target Diameter server, known as the home Diameter server, - SHOULD respond with the Accounting-Answer command. - - In addition to the AVPs listed below, Accounting-Answer messages - SHOULD include service-specific accounting AVPs. - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 128] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ACA> ::= < Diameter Header: 271, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - { Accounting-Record-Type } - { Accounting-Record-Number } - [ Acct-Application-Id ] - [ Vendor-Specific-Application-Id ] - [ User-Name ] - [ Accounting-Sub-Session-Id ] - [ Acct-Session-Id ] - [ Acct-Multi-Session-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Acct-Interim-Interval ] - [ Accounting-Realtime-Required ] - [ Origin-State-Id ] - [ Event-Timestamp ] - * [ Proxy-Info ] - * [ AVP ] - -9.8. Accounting AVPs - - This section contains AVPs that describe accounting usage information - related to a specific session. - -9.8.1. Accounting-Record-Type AVP - - The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated - and contains the type of accounting record being sent. The following - values are currently defined for the Accounting-Record-Type AVP: - - EVENT_RECORD 1 - - An Accounting Event Record is used to indicate that a one-time - event has occurred (meaning that the start and end of the event - are simultaneous). This record contains all information relevant - to the service, and it is the only record of the service. - - - - - - - - - -Fajardo, et al. Standards Track [Page 129] - -RFC 6733 Diameter Base Protocol October 2012 - - - START_RECORD 2 - - Accounting Start, Interim, and Stop Records are used to indicate - that a service of a measurable length has been given. An - Accounting Start Record is used to initiate an accounting session - and contains accounting information that is relevant to the - initiation of the session. - - INTERIM_RECORD 3 - - An Interim Accounting Record contains cumulative accounting - information for an existing accounting session. Interim - Accounting Records SHOULD be sent every time a re-authentication - or re-authorization occurs. Further, additional interim record - triggers MAY be defined by application-specific Diameter - applications. The selection of whether to use INTERIM_RECORD - records is done by the Acct-Interim-Interval AVP. - - STOP_RECORD 4 - - An Accounting Stop Record is sent to terminate an accounting - session and contains cumulative accounting information relevant to - the existing session. - -9.8.2. Acct-Interim-Interval AVP - - The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and - is sent from the Diameter home authorization server to the Diameter - client. The client uses information in this AVP to decide how and - when to produce accounting records. With different values in this - AVP, service sessions can result in one, two, or two+N accounting - records, based on the needs of the home organization. The following - accounting record production behavior is directed by the inclusion of - this AVP: - - 1. The omission of the Acct-Interim-Interval AVP or its inclusion - with Value field set to 0 means that EVENT_RECORD, START_RECORD, - and STOP_RECORD are produced, as appropriate for the service. - - 2. The inclusion of the AVP with Value field set to a non-zero value - means that INTERIM_RECORD records MUST be produced between the - START_RECORD and STOP_RECORD records. The Value field of this - AVP is the nominal interval between these records in seconds. - The Diameter node that originates the accounting information, - known as the client, MUST produce the first INTERIM_RECORD record - roughly at the time when this nominal interval has elapsed from - - - - - -Fajardo, et al. Standards Track [Page 130] - -RFC 6733 Diameter Base Protocol October 2012 - - - the START_RECORD, the next one again as the interval has elapsed - once more, and so on until the session ends and a STOP_RECORD - record is produced. - - The client MUST ensure that the interim record production times - are randomized so that large accounting message storms are not - created either among records or around a common service start - time. - -9.8.3. Accounting-Record-Number AVP - - The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32 - and identifies this record within one session. As Session-Id AVPs - are globally unique, the combination of Session-Id and Accounting- - Record-Number AVPs is also globally unique and can be used in - matching accounting records with confirmations. An easy way to - produce unique numbers is to set the value to 0 for records of type - EVENT_RECORD and START_RECORD and set the value to 1 for the first - INTERIM_RECORD, 2 for the second, and so on until the value for - STOP_RECORD is one more than for the last INTERIM_RECORD. - -9.8.4. Acct-Session-Id AVP - - The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only - used when RADIUS/Diameter translation occurs. This AVP contains the - contents of the RADIUS Acct-Session-Id attribute. - -9.8.5. Acct-Multi-Session-Id AVP - - The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String, - following the format specified in Section 8.8. The Acct-Multi- - Session-Id AVP is used to link multiple related accounting sessions, - where each session would have a unique Session-Id but the same Acct- - Multi-Session-Id AVP. This AVP MAY be returned by the Diameter - server in an authorization answer, and it MUST be used in all - accounting messages for the given session. - -9.8.6. Accounting-Sub-Session-Id AVP - - The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type - Unsigned64 and contains the accounting sub-session identifier. The - combination of the Session-Id and this AVP MUST be unique per sub- - session, and the value of this AVP MUST be monotonically increased by - one for all new sub-sessions. The absence of this AVP implies no - sub-sessions are in use, with the exception of an Accounting-Request - whose Accounting-Record-Type is set to STOP_RECORD. A STOP_RECORD - message with no Accounting-Sub-Session-Id AVP present will signal the - termination of all sub-sessions for a given Session-Id. - - - -Fajardo, et al. Standards Track [Page 131] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.8.7. Accounting-Realtime-Required AVP - - The Accounting-Realtime-Required AVP (AVP Code 483) is of type - Enumerated and is sent from the Diameter home authorization server to - the Diameter client or in the Accounting-Answer from the accounting - server. The client uses information in this AVP to decide what to do - if the sending of accounting records to the accounting server has - been temporarily prevented due to, for instance, a network problem. - - DELIVER_AND_GRANT 1 - - The AVP with Value field set to DELIVER_AND_GRANT means that the - service MUST only be granted as long as there is a connection to - an accounting server. Note that the set of alternative accounting - servers are treated as one server in this sense. Having to move - the accounting record stream to a backup server is not a reason to - discontinue the service to the user. - - GRANT_AND_STORE 2 - - The AVP with Value field set to GRANT_AND_STORE means that service - SHOULD be granted if there is a connection, or as long as records - can still be stored as described in Section 9.4. - - This is the default behavior if the AVP isn't included in the - reply from the authorization server. - - GRANT_AND_LOSE 3 - - The AVP with Value field set to GRANT_AND_LOSE means that service - SHOULD be granted even if the records cannot be delivered or - stored. - -10. AVP Occurrence Tables - - The following tables present the AVPs defined in this document and - specify in which Diameter messages they MAY or MAY NOT be present. - AVPs that occur only inside a Grouped AVP are not shown in these - tables. - - The tables use the following symbols: - - 0 The AVP MUST NOT be present in the message. - - 0+ Zero or more instances of the AVP MAY be present in the - message. - - - - - -Fajardo, et al. Standards Track [Page 132] - -RFC 6733 Diameter Base Protocol October 2012 - - - 0-1 Zero or one instance of the AVP MAY be present in the message. - It is considered an error if there are more than one instance - of the AVP. - - 1 One instance of the AVP MUST be present in the message. - - 1+ At least one instance of the AVP MUST be present in the - message. - -10.1. Base Protocol Command AVP Table - - The table in this section is limited to the non-Accounting Command - Codes defined in this specification. - - +-----------------------------------------------+ - | Command Code | - +---+---+---+---+---+---+---+---+---+---+---+---+ - Attribute Name |CER|CEA|DPR|DPA|DWR|DWA|RAR|RAA|ASR|ASA|STR|STA| - --------------------+---+---+---+---+---+---+---+---+---+---+---+---+ - Acct-Interim- |0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 | - Interval | | | | | | | | | | | | | - Accounting-Realtime-|0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 | - Required | | | | | | | | | | | | | - Acct-Application-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Application-Id |0+ |0+ |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 | - Auth-Grace-Period |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Request-Type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Session-State |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Authorization- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Lifetime | | | | | | | | | | | | | - Class |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0+ |0+ | - Destination-Host |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |0-1|0 | - Destination-Realm |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 | - Disconnect-Cause |0 |0 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Error-Message |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1| - Error-Reporting-Host|0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Failed-AVP |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1| - Firmware-Revision |0-1|0-1|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Host-IP-Address |1+ |1+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Inband-Security-Id |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Multi-Round-Time-Out|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - - - - - - - - - - -Fajardo, et al. Standards Track [Page 133] - -RFC 6733 Diameter Base Protocol October 2012 - - - Origin-Host |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 | - Origin-Realm |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 | - Origin-State-Id |0-1|0-1|0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|0-1|0-1| - Product-Name |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Proxy-Info |0 |0 |0 |0 |0 |0 |0+ |0+ |0+ |0+ |0+ |0+ | - Redirect-Host |0 |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ | - Redirect-Host-Usage |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Redirect-Max-Cache- |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Time | | | | | | | | | | | | | - Result-Code |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 | - Re-Auth-Request-Type|0 |0 |0 |0 |0 |0 |1 |0 |0 |0 |0 |0 | - Route-Record |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |0 | - Session-Binding |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Session-Id |0 |0 |0 |0 |0 |0 |1 |1 |1 |1 |1 |1 | - Session-Server- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Failover | | | | | | | | | | | | | - Session-Timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Supported-Vendor-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Termination-Cause |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |1 |0 | - User-Name |0 |0 |0 |0 |0 |0 |0-1|0-1|0-1|0-1|0-1|0-1| - Vendor-Id |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Vendor-Specific- |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Application-Id | | | | | | | | | | | | | - --------------------+---+---+---+---+---+---+---+---+---+---+---+---+ - -10.2. Accounting AVP Table - - The table in this section is used to represent which AVPs defined in - this document are to be present in the Accounting messages. These - AVP occurrence requirements are guidelines, which may be expanded, - and/or overridden by application-specific requirements in the - Diameter applications documents. - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 134] - -RFC 6733 Diameter Base Protocol October 2012 - - - +-----------+ - | Command | - | Code | - +-----+-----+ - Attribute Name | ACR | ACA | - ------------------------------+-----+-----+ - Acct-Interim-Interval | 0-1 | 0-1 | - Acct-Multi-Session-Id | 0-1 | 0-1 | - Accounting-Record-Number | 1 | 1 | - Accounting-Record-Type | 1 | 1 | - Acct-Session-Id | 0-1 | 0-1 | - Accounting-Sub-Session-Id | 0-1 | 0-1 | - Accounting-Realtime-Required | 0-1 | 0-1 | - Acct-Application-Id | 0-1 | 0-1 | - Auth-Application-Id | 0 | 0 | - Class | 0+ | 0+ | - Destination-Host | 0-1 | 0 | - Destination-Realm | 1 | 0 | - Error-Reporting-Host | 0 | 0+ | - Event-Timestamp | 0-1 | 0-1 | - Failed-AVP | 0 | 0-1 | - Origin-Host | 1 | 1 | - Origin-Realm | 1 | 1 | - Proxy-Info | 0+ | 0+ | - Route-Record | 0+ | 0 | - Result-Code | 0 | 1 | - Session-Id | 1 | 1 | - Termination-Cause | 0 | 0 | - User-Name | 0-1 | 0-1 | - Vendor-Specific-Application-Id| 0-1 | 0-1 | - ------------------------------+-----+-----+ - -11. IANA Considerations - - This section provides guidance to the Internet Assigned Numbers - Authority (IANA) regarding registration of values related to the - Diameter protocol, in accordance with [RFC5226]. Existing IANA - registries and assignments put in place by RFC 3588 remain the same - unless explicitly updated or deprecated in this section. - -11.1. AVP Header - - As defined in Section 4, the AVP header contains three fields that - require IANA namespace management: the AVP Code, Vendor-ID, and Flags - fields. - - - - - - -Fajardo, et al. Standards Track [Page 135] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.1.1. AVP Codes - - There are multiple namespaces. Vendors can have their own AVP Codes - namespace that will be identified by their Vendor-ID (also known as - Enterprise-Number), and they control the assignments of their vendor- - specific AVP Codes within their own namespace. The absence of a - Vendor-ID or a Vendor-ID value of zero (0) identifies the IETF AVP - Codes namespace, which is under IANA control. The AVP Codes and - sometimes possible values in an AVP are controlled and maintained by - IANA. AVP Code 0 is not used. AVP Codes 1-255 are managed - separately as RADIUS Attribute Types. Where a Vendor-Specific AVP is - implemented by more than one vendor, allocation of global AVPs should - be encouraged instead. - - AVPs may be allocated following Expert Review (by a Designated - Expert) with Specification Required [RFC5226]. A block allocation - (release of more than three AVPs at a time for a given purpose) - requires IETF Review [RFC5226]. - -11.1.2. AVP Flags - - Section 4.1 describes the existing AVP Flags. The remaining bits can - only be assigned via a Standards Action [RFC5226]. - -11.2. Diameter Header - -11.2.1. Command Codes - - For the Diameter header, the Command Code namespace allocation has - changed. The new allocation rules are as follows: - - The Command Code values 256 - 8,388,607 (0x100 to 0x7fffff) are - for permanent, standard commands, allocated by IETF Review - [RFC5226]. - - The values 8,388,608 - 16,777,213 (0x800000 - 0xfffffd) are - reserved for vendor-specific Command Codes, to be allocated on a - First Come, First Served basis by IANA [RFC5226]. The request to - IANA for a Vendor-Specific Command Code SHOULD include a reference - to a publicly available specification that documents the command - in sufficient detail to aid in interoperability between - independent implementations. If the specification cannot be made - publicly available, the request for a vendor-specific Command Code - MUST include the contact information of persons and/or entities - responsible for authoring and maintaining the command. - - - - - - -Fajardo, et al. Standards Track [Page 136] - -RFC 6733 Diameter Base Protocol October 2012 - - - The values 16,777,214 and 16,777,215 (hexadecimal values 0xfffffe - - 0xffffff) are reserved for experimental commands. As these - codes are only for experimental and testing purposes, no guarantee - is made for interoperability between Diameter peers using - experimental commands. - -11.2.2. Command Flags - - Section 3 describes the existing Command Flags field. The remaining - bits can only be assigned via a Standards Action [RFC5226]. - -11.3. AVP Values - - For AVP values, the Experimental-Result-Code AVP value allocation has - been added; see Section 11.3.1. The old AVP value allocation rule, - IETF Consensus, has been updated to IETF Review as per [RFC5226], and - affected AVPs are listed as reminders. - -11.3.1. Experimental-Result-Code AVP - - Values for this AVP are purely local to the indicated vendor, and no - IANA registry is maintained for them. - -11.3.2. Result-Code AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.3. Accounting-Record-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.4. Termination-Cause AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.5. Redirect-Host-Usage AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.6. Session-Server-Failover AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.7. Session-Binding AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - - - - - -Fajardo, et al. Standards Track [Page 137] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.3.8. Disconnect-Cause AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.9. Auth-Request-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.10. Auth-Session-State AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.11. Re-Auth-Request-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.12. Accounting-Realtime-Required AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.13. Inband-Security-Id AVP (code 299) - - The use of this AVP has been deprecated. - -11.4. _diameters Service Name and Port Number Registration - - IANA has registered the "_diameters" service name and assigned port - numbers for TLS/TCP and DTLS/SCTP according to the guidelines given - in [RFC6335]. - - Service Name: _diameters - - Transport Protocols: TCP, SCTP - - Assignee: IESG <[email protected]> - - Contact: IETF Chair <[email protected]> - - Description: Diameter over TLS/TCP and DTLS/SCTP - - Reference: RFC 6733 - - Port Number: 5868, from the User Range - - - - - - - - -Fajardo, et al. Standards Track [Page 138] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.5. SCTP Payload Protocol Identifiers - - Two SCTP payload protocol identifiers have been registered in the - SCTP Payload Protocol Identifiers registry: - - - Value | SCTP Payload Protocol Identifier - -------|----------------------------------- - 46 | Diameter in a SCTP DATA chunk - 47 | Diameter in a DTLS/SCTP DATA chunk - - -11.6. S-NAPTR Parameters - - The following tag has been registered in the S-NAPTR Application - Protocol Tags registry: - - Tag | Protocol - -------------------|--------- - diameter.dtls.sctp | DTLS/SCTP - -12. Diameter Protocol-Related Configurable Parameters - - This section contains the configurable parameters that are found - throughout this document: - - Diameter Peer - - A Diameter entity MAY communicate with peers that are statically - configured. A statically configured Diameter peer would require - that either the IP address or the fully qualified domain name - (FQDN) be supplied, which would then be used to resolve through - DNS. - - Routing Table - - A Diameter proxy server routes messages based on the realm portion - of a Network Access Identifier (NAI). The server MUST have a - table of Realm Names, and the address of the peer to which the - message must be forwarded. The routing table MAY also include a - "default route", which is typically used for all messages that - cannot be locally processed. - - Tc timer - - The Tc timer controls the frequency that transport connection - attempts are done to a peer with whom no active transport - connection exists. The recommended value is 30 seconds. - - - -Fajardo, et al. Standards Track [Page 139] - -RFC 6733 Diameter Base Protocol October 2012 - - -13. Security Considerations - - The Diameter base protocol messages SHOULD be secured by using TLS - [RFC5246] or DTLS/SCTP [RFC6083]. Additional security mechanisms - such as IPsec [RFC4301] MAY also be deployed to secure connections - between peers. However, all Diameter base protocol implementations - MUST support the use of TLS/TCP and DTLS/SCTP, and the Diameter - protocol MUST NOT be used without one of TLS, DTLS, or IPsec. - - If a Diameter connection is to be protected via TLS/TCP and DTLS/SCTP - or IPsec, then TLS/TCP and DTLS/SCTP or IPsec/IKE SHOULD begin prior - to any Diameter message exchange. All security parameters for TLS/ - TCP and DTLS/SCTP or IPsec are configured independent of the Diameter - protocol. All Diameter messages will be sent through the TLS/TCP and - DTLS/SCTP or IPsec connection after a successful setup. - - For TLS/TCP and DTLS/SCTP connections to be established in the open - state, the CER/CEA exchange MUST include an Inband-Security-ID AVP - with a value of TLS/TCP and DTLS/SCTP. The TLS/TCP and DTLS/SCTP - handshake will begin when both ends successfully reach the open - state, after completion of the CER/CEA exchange. If the TLS/TCP and - DTLS/SCTP handshake is successful, all further messages will be sent - via TLS/TCP and DTLS/SCTP. If the handshake fails, both ends MUST - move to the closed state. See Section 13.1 for more details. - -13.1. TLS/TCP and DTLS/SCTP Usage - - Diameter nodes using TLS/TCP and DTLS/SCTP for security MUST mutually - authenticate as part of TLS/TCP and DTLS/SCTP session establishment. - In order to ensure mutual authentication, the Diameter node acting as - the TLS/TCP and DTLS/SCTP server MUST request a certificate from the - Diameter node acting as TLS/TCP and DTLS/SCTP client, and the - Diameter node acting as the TLS/TCP and DTLS/SCTP client MUST be - prepared to supply a certificate on request. - - Diameter nodes MUST be able to negotiate the following TLS/TCP and - DTLS/SCTP cipher suites: - - TLS_RSA_WITH_RC4_128_MD5 - TLS_RSA_WITH_RC4_128_SHA - TLS_RSA_WITH_3DES_EDE_CBC_SHA - - Diameter nodes SHOULD be able to negotiate the following TLS/TCP and - DTLS/SCTP cipher suite: - - TLS_RSA_WITH_AES_128_CBC_SHA - - - - - -Fajardo, et al. Standards Track [Page 140] - -RFC 6733 Diameter Base Protocol October 2012 - - - Note that it is quite possible that support for the - TLS_RSA_WITH_AES_128_CBC_SHA cipher suite will be REQUIRED at some - future date. Diameter nodes MAY negotiate other TLS/TCP and DTLS/ - SCTP cipher suites. - - If public key certificates are used for Diameter security (for - example, with TLS), the value of the expiration times in the routing - and peer tables MUST NOT be greater than the expiry time in the - relevant certificates. - -13.2. Peer-to-Peer Considerations - - As with any peer-to-peer protocol, proper configuration of the trust - model within a Diameter peer is essential to security. When - certificates are used, it is necessary to configure the root - certificate authorities trusted by the Diameter peer. These root CAs - are likely to be unique to Diameter usage and distinct from the root - CAs that might be trusted for other purposes such as Web browsing. - In general, it is expected that those root CAs will be configured so - as to reflect the business relationships between the organization - hosting the Diameter peer and other organizations. As a result, a - Diameter peer will typically not be configured to allow connectivity - with any arbitrary peer. With certificate authentication, Diameter - peers may not be known beforehand and therefore peer discovery may be - required. - -13.3. AVP Considerations - - Diameter AVPs often contain security-sensitive data; for example, - user passwords and location data, network addresses and cryptographic - keys. The following AVPs defined in this document are considered to - be security-sensitive: - - o Acct-Interim-Interval - - o Accounting-Realtime-Required - - o Acct-Multi-Session-Id - - o Accounting-Record-Number - - o Accounting-Record-Type - - o Accounting-Session-Id - - o Accounting-Sub-Session-Id - - o Class - - - -Fajardo, et al. Standards Track [Page 141] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Session-Id - - o Session-Binding - - o Session-Server-Failover - - o User-Name - - Diameter messages containing these or any other AVPs considered to be - security-sensitive MUST only be sent protected via mutually - authenticated TLS or IPsec. In addition, those messages MUST NOT be - sent via intermediate nodes unless there is end-to-end security - between the originator and recipient or the originator has locally - trusted configuration that indicates that end-to-end security is not - needed. For example, end-to-end security may not be required in the - case where an intermediary node is known to be operated as part of - the same administrative domain as the endpoints so that an ability to - successfully compromise the intermediary would imply a high - probability of being able to compromise the endpoints as well. Note - that no end-to-end security mechanism is specified in this document. - -14. References - -14.1. Normative References - - [FLOATPOINT] - Institute of Electrical and Electronics Engineers, "IEEE - Standard for Binary Floating-Point Arithmetic, ANSI/IEEE - Standard 754-1985", August 1985. - - [IANAADFAM] - IANA, "Address Family Numbers", - <http://www.iana.org/assignments/address-family-numbers>. - - [RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791, - September 1981. - - [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, - RFC 793, September 1981. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC3492] Costello, A., "Punycode: A Bootstring encoding of Unicode - for Internationalized Domain Names in Applications - (IDNA)", RFC 3492, March 2003. - - - - - -Fajardo, et al. Standards Track [Page 142] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC3539] Aboba, B. and J. Wood, "Authentication, Authorization and - Accounting (AAA) Transport Profile", RFC 3539, June 2003. - - [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", STD 63, RFC 3629, November 2003. - - [RFC3958] Daigle, L. and A. Newton, "Domain-Based Application - Service Location Using SRV RRs and the Dynamic Delegation - Discovery Service (DDDS)", RFC 3958, January 2005. - - [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform - Resource Identifier (URI): Generic Syntax", STD 66, - RFC 3986, January 2005. - - [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T., and - P. McCann, "Diameter Mobile IPv4 Application", RFC 4004, - August 2005. - - [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton, - "Diameter Network Access Server Application", RFC 4005, - August 2005. - - [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M., and J. - Loughney, "Diameter Credit-Control Application", RFC 4006, - August 2005. - - [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness - Requirements for Security", BCP 106, RFC 4086, June 2005. - - [RFC4282] Aboba, B., Beadles, M., Arkko, J., and P. Eronen, "The - Network Access Identifier", RFC 4282, December 2005. - - [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing - Architecture", RFC 4291, February 2006. - - [RFC4960] Stewart, R., "Stream Control Transmission Protocol", - RFC 4960, September 2007. - - [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an - IANA Considerations Section in RFCs", BCP 26, RFC 5226, - May 2008. - - [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", STD 68, RFC 5234, January 2008. - - [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security - (TLS) Protocol Version 1.2", RFC 5246, August 2008. - - - - -Fajardo, et al. Standards Track [Page 143] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., - Housley, R., and W. Polk, "Internet X.509 Public Key - Infrastructure Certificate and Certificate Revocation List - (CRL) Profile", RFC 5280, May 2008. - - [RFC5729] Korhonen, J., Jones, M., Morand, L., and T. Tsou, - "Clarifications on the Routing of Diameter Requests Based - on the Username and the Realm", RFC 5729, December 2009. - - [RFC5890] Klensin, J., "Internationalized Domain Names for - Applications (IDNA): Definitions and Document Framework", - RFC 5890, August 2010. - - [RFC5891] Klensin, J., "Internationalized Domain Names in - Applications (IDNA): Protocol", RFC 5891, August 2010. - - [RFC6083] Tuexen, M., Seggelmann, R., and E. Rescorla, "Datagram - Transport Layer Security (DTLS) for Stream Control - Transmission Protocol (SCTP)", RFC 6083, January 2011. - - [RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer - Security Version 1.2", RFC 6347, January 2012. - - [RFC6408] Jones, M., Korhonen, J., and L. Morand, "Diameter - Straightforward-Naming Authority Pointer (S-NAPTR) Usage", - RFC 6408, November 2011. - -14.2. Informative References - - [ENTERPRISE] IANA, "SMI Network Management Private Enterprise - Codes", - <http://www.iana.org/assignments/enterprise-numbers>. - - [IANATCV] IANA, "Termination-Cause AVP Values (code 295)", - <http://www.iana.org/assignments/aaa-parameters/ - aaa-parameters.xml#aaa-parameters-16>. - - [RFC1492] Finseth, C., "An Access Control Protocol, Sometimes - Called TACACS", RFC 1492, July 1993. - - [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)", - STD 51, RFC 1661, July 1994. - - [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: - Keyed-Hashing for Message Authentication", RFC 2104, - February 1997. - - - - - -Fajardo, et al. Standards Track [Page 144] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR - for specifying the location of services (DNS SRV)", - RFC 2782, February 2000. - - [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson, - "Remote Authentication Dial In User Service (RADIUS)", - RFC 2865, June 2000. - - [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000. - - [RFC2869] Rigney, C., Willats, W., and P. Calhoun, "RADIUS - Extensions", RFC 2869, June 2000. - - [RFC2881] Mitton, D. and M. Beadles, "Network Access Server - Requirements Next Generation (NASREQNG) NAS Model", - RFC 2881, July 2000. - - [RFC2975] Aboba, B., Arkko, J., and D. Harrington, "Introduction - to Accounting Management", RFC 2975, October 2000. - - [RFC2989] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann, - P., Shiino, H., Walsh, P., Zorn, G., Dommety, G., - Perkins, C., Patil, B., Mitton, D., Manning, S., - Beadles, M., Chen, X., Sivalingham, S., Hameed, A., - Munson, M., Jacobs, S., Lim, B., Hirschman, B., Hsu, - R., Koo, H., Lipford, M., Campbell, E., Xu, Y., Baba, - S., and E. Jaques, "Criteria for Evaluating AAA - Protocols for Network Access", RFC 2989, November 2000. - - [RFC3162] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6", - RFC 3162, August 2001. - - [RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and - H. Levkowetz, "Extensible Authentication Protocol - (EAP)", RFC 3748, June 2004. - - [RFC4301] Kent, S. and K. Seo, "Security Architecture for the - Internet Protocol", RFC 4301, December 2005. - - [RFC4690] Klensin, J., Faltstrom, P., Karp, C., and IAB, "Review - and Recommendations for Internationalized Domain Names - (IDNs)", RFC 4690, September 2006. - - [RFC5176] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B. - Aboba, "Dynamic Authorization Extensions to Remote - Authentication Dial In User Service (RADIUS)", - RFC 5176, January 2008. - - - - -Fajardo, et al. Standards Track [Page 145] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC5461] Gont, F., "TCP's Reaction to Soft Errors", RFC 5461, - February 2009. - - [RFC5905] Mills, D., Martin, J., Burbank, J., and W. Kasch, - "Network Time Protocol Version 4: Protocol and - Algorithms Specification", RFC 5905, June 2010. - - [RFC5927] Gont, F., "ICMP Attacks against TCP", RFC 5927, - July 2010. - - [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and - S. Cheshire, "Internet Assigned Numbers Authority - (IANA) Procedures for the Management of the Service - Name and Transport Protocol Port Number Registry", - BCP 165, RFC 6335, August 2011. - - [RFC6737] Kang, J. and G. Zorn, "The Diameter Capabilities Update - Application", RFC 6737, October 2012. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 146] - -RFC 6733 Diameter Base Protocol October 2012 - - -Appendix A. Acknowledgements - -A.1. This Document - - The authors would like to thank the following people that have - provided proposals and contributions to this document: - - To Vishnu Ram and Satendra Gera for their contributions on - capabilities updates, predictive loop avoidance, as well as many - other technical proposals. To Tolga Asveren for his insights and - contributions on almost all of the proposed solutions incorporated - into this document. To Timothy Smith for helping on the capabilities - Update and other topics. To Tony Zhang for providing fixes to - loopholes on composing Failed-AVPs as well as many other issues and - topics. To Jan Nordqvist for clearly stating the usage of - Application Ids. To Anders Kristensen for providing needed technical - opinions. To David Frascone for providing invaluable review of the - document. To Mark Jones for providing clarifying text on vendor - command codes and other vendor-specific indicators. To Victor - Pascual and Sebastien Decugis for new text and recommendations on - SCTP/DTLS. To Jouni Korhonen for taking over the editing task and - resolving last bits from versions 27 through 29. - - Special thanks to the Diameter extensibility design team, which - helped resolve the tricky question of mandatory AVPs and ABNF - semantics. The members of this team are as follows: - - Avi Lior, Jari Arkko, Glen Zorn, Lionel Morand, Mark Jones, Tolga - Asveren, Jouni Korhonen, and Glenn McGregor. - - Special thanks also to people who have provided invaluable comments - and inputs especially in resolving controversial issues: - - Glen Zorn, Yoshihiro Ohba, Marco Stura, Stephen Farrel, Pete Resnick, - Peter Saint-Andre, Robert Sparks, Krishna Prasad, Sean Turner, Barry - Leiba, and Pasi Eronen. - - Finally, we would like to thank the original authors of this - document: - - Pat Calhoun, John Loughney, Jari Arkko, Erik Guttman, and Glen Zorn. - - Their invaluable knowledge and experience has given us a robust and - flexible AAA protocol that many people have seen great value in - adopting. We greatly appreciate their support and stewardship for - the continued improvements of Diameter as a protocol. We would also - like to extend our gratitude to folks aside from the authors who have - - - - -Fajardo, et al. Standards Track [Page 147] - -RFC 6733 Diameter Base Protocol October 2012 - - - assisted and contributed to the original version of this document. - Their efforts significantly contributed to the success of Diameter. - -A.2. RFC 3588 - - The authors would like to thank Nenad Trifunovic, Tony Johansson and - Pankaj Patel for their participation in the pre-IETF Document Reading - Party. Allison Mankin, Jonathan Wood, and Bernard Aboba provided - invaluable assistance in working out transport issues and this was - also the case with Steven Bellovin in the security area. - - Paul Funk and David Mitton were instrumental in getting the Peer - State Machine correct, and our deep thanks go to them for their time. - - Text in this document was also provided by Paul Funk, Mark Eklund, - Mark Jones, and Dave Spence. Jacques Caron provided many great - comments as a result of a thorough review of the spec. - - The authors would also like to acknowledge the following people for - their contribution in the development of the Diameter protocol: - - Allan C. Rubens, Haseeb Akhtar, William Bulley, Stephen Farrell, - David Frascone, Daniel C. Fox, Lol Grant, Ignacio Goyret, Nancy - Greene, Peter Heitman, Fredrik Johansson, Mark Jones, Martin Julien, - Bob Kopacz, Paul Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin, - Kenneth Peirce, John Schnizlein, Sumit Vakil, John R. Vollbrecht, and - Jeff Weisberg. - - Finally, Pat Calhoun would like to thank Sun Microsystems since most - of the effort put into this document was done while he was in their - employ. - -Appendix B. S-NAPTR Example - - As an example, consider a client that wishes to resolve aaa: - ex1.example.com. The client performs a NAPTR query for that domain, - and the following NAPTR records are returned: - - ;; order pref flags service regexp replacement - IN NAPTR 50 50 "s" "aaa:diameter.tls.tcp" "" - _diameter._tls.ex1.example.com - IN NAPTR 100 50 "s" "aaa:diameter.tcp" "" - _aaa._tcp.ex1.example.com - IN NAPTR 150 50 "s" "aaa:diameter.sctp" "" - _diameter._sctp.ex1.example.com - - This indicates that the server supports TLS, TCP, and SCTP in that - order. If the client supports TLS, TLS will be used, targeted to a - - - -Fajardo, et al. Standards Track [Page 148] - -RFC 6733 Diameter Base Protocol October 2012 - - - host determined by an SRV lookup of _diameter._tls.ex1.example.com. - That lookup would return: - - ;; Priority Weight Port Target - IN SRV 0 1 5060 server1.ex1.example.com - IN SRV 0 2 5060 server2.ex1.example.com - - As an alternative example, a client that wishes to resolve aaa: - ex2.example.com. The client performs a NAPTR query for that domain, - and the following NAPTR records are returned: - - ;; order pref flags service regexp replacement - IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" "" - server1.ex2.example.com - IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" "" - server2.ex2.example.com - - This indicates that the server supports TCP available at the returned - host names. - -Appendix C. Duplicate Detection - - As described in Section 9.4, accounting record duplicate detection is - based on session identifiers. Duplicates can appear for various - reasons: - - o Failover to an alternate server. Where close to real-time - performance is required, failover thresholds need to be kept low. - This may lead to an increased likelihood of duplicates. Failover - can occur at the client or within Diameter agents. - - o Failure of a client or agent after sending a record from non- - volatile memory, but prior to receipt of an application-layer ACK - and deletion of the record to be sent. This will result in - retransmission of the record soon after the client or agent has - rebooted. - - o Duplicates received from RADIUS gateways. Since the - retransmission behavior of RADIUS is not defined within [RFC2865], - the likelihood of duplication will vary according to the - implementation. - - o Implementation problems and misconfiguration. - - The T flag is used as an indication of an application-layer - retransmission event, e.g., due to failover to an alternate server. - It is defined only for request messages sent by Diameter clients or - agents. For instance, after a reboot, a client may not know whether - - - -Fajardo, et al. Standards Track [Page 149] - -RFC 6733 Diameter Base Protocol October 2012 - - - it has already tried to send the accounting records in its non- - volatile memory before the reboot occurred. Diameter servers MAY use - the T flag as an aid when processing requests and detecting duplicate - messages. However, servers that do this MUST ensure that duplicates - are found even when the first transmitted request arrives at the - server after the retransmitted request. It can be used only in cases - where no answer has been received from the server for a request and - the request is sent again, (e.g., due to a failover to an alternate - peer, due to a recovered primary peer or due to a client re-sending a - stored record from non-volatile memory such as after reboot of a - client or agent). - - In some cases, the Diameter accounting server can delay the duplicate - detection and accounting record processing until a post-processing - phase takes place. At that time records are likely to be sorted - according to the included User-Name and duplicate elimination is easy - in this case. In other situations, it may be necessary to perform - real-time duplicate detection, such as when credit limits are imposed - or real-time fraud detection is desired. - - In general, only generation of duplicates due to failover or re- - sending of records in non-volatile storage can be reliably detected - by Diameter clients or agents. In such cases, the Diameter client or - agents can mark the message as a possible duplicate by setting the T - flag. Since the Diameter server is responsible for duplicate - detection, it can choose whether or not to make use of the T flag, in - order to optimize duplicate detection. Since the T flag does not - affect interoperability, and it may not be needed by some servers, - generation of the T flag is REQUIRED for Diameter clients and agents, - but it MAY be implemented by Diameter servers. - - As an example, it can be usually be assumed that duplicates appear - within a time window of longest recorded network partition or device - fault, perhaps a day. So only records within this time window need - to be looked at in the backward direction. Secondly, hashing - techniques or other schemes, such as the use of the T flag in the - received messages, may be used to eliminate the need to do a full - search even in this set except for rare cases. - - The following is an example of how the T flag may be used by the - server to detect duplicate requests. - - A Diameter server MAY check the T flag of the received message to - determine if the record is a possible duplicate. If the T flag is - set in the request message, the server searches for a duplicate - within a configurable duplication time window backward and - forward. This limits database searching to those records where - the T flag is set. In a well-run network, network partitions and - - - -Fajardo, et al. Standards Track [Page 150] - -RFC 6733 Diameter Base Protocol October 2012 - - - device faults will presumably be rare events, so this approach - represents a substantial optimization of the duplicate detection - process. During failover, it is possible for the original record - to be received after the T-flag-marked record, due to differences - in network delays experienced along the path by the original and - duplicate transmissions. The likelihood of this occurring - increases as the failover interval is decreased. In order to be - able to detect duplicates that are out of order, the Diameter - server should use backward and forward time windows when - performing duplicate checking for the T-flag-marked request. For - example, in order to allow time for the original record to exit - the network and be recorded by the accounting server, the Diameter - server can delay processing records with the T flag set until a - time period TIME_WAIT + RECORD_PROCESSING_TIME has elapsed after - the closing of the original transport connection. After this time - period, it may check the T-flag-marked records against the - database with relative assurance that the original records, if - sent, have been received and recorded. - -Appendix D. Internationalized Domain Names - - To be compatible with the existing DNS infrastructure and simplify - host and domain name comparison, Diameter identities (FQDNs) are - represented in ASCII form. This allows the Diameter protocol to fall - in-line with the DNS strategy of being transparent from the effects - of Internationalized Domain Names (IDNs) by following the - recommendations in [RFC4690] and [RFC5890]. Applications that - provide support for IDNs outside of the Diameter protocol but - interacting with it SHOULD use the representation and conversion - framework described in [RFC5890], [RFC5891], and [RFC3492]. -</pre> - -</section> diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml index 1d65d14257..9f84eeb9fd 100644 --- a/lib/diameter/doc/src/diameter_tcp.xml +++ b/lib/diameter/doc/src/diameter_tcp.xml @@ -27,7 +27,8 @@ <erlref> <header> <copyright> -<year>2011</year><year>2016</year> +<year>2011</year> +<year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -99,7 +100,9 @@ before configuring TLS capability on diameter transports.</p> | {rport, integer()} | {accept, Match} | {port, integer()} - | {fragment_timer, infinity | 0..16#FFFFFFFF}</v> + | {fragment_timer, infinity | 0..16#FFFFFFFF} + | {message_cb, &mod_eval;} + | {sender, boolean()}</v> <v>SslOpt = {ssl_options, true | list()}</v> <v>TcpOpt = term()</v> <v>Match = &ip_address; | string() | [Match]</v> @@ -140,6 +143,44 @@ such a message is received over the transport interface after two successive timeouts without the reception of additional bytes. Defaults to 1000.</p> +<marker id="sender"/> +<p> +Option <c>sender</c> specifies whether or not to use a dedicated +process for sending outgoing messages, which avoids the possibility of +send blocking reception. +Defaults to <c>false</c>. +If set to <c>true</c> then a <c>message_cb</c> that avoids the +possibility of messages being queued in the sender process without +bound should be configured.</p> + +<p> +Option <c>message_cb</c> specifies a callback that is invoked on +incoming and outgoing messages, that can be used to implement +flow control. +It is applied to two arguments: an atom indicating the +reason for the callback (<c>send</c>, <c>recv</c>, or <c>ack</c> after +a completed send), and the message in question (binary() on +<c>recv</c>, binary() or diameter_packet record on <c>send</c> or +<c>ack</c>, or <c>false</c> on <c>ack</c> when an incoming request has +been discarded). +It should return a list of actions and a new callback as +tail; eg. <c>[fun cb/3, State]</c>. +Valid actions are the atoms <c>send</c> or <c>recv</c>, to +cause a following message-valued action to be sent/received, +a message to send/receive (binary() or +diameter_packet record), or a boolean() to enable/disable reading on +the socket. +More than one <c>send</c>/<c>recv</c>/message sequence can be +returned from the same callback, and an initial +<c>send</c>/<c>recv</c> can be omitted if the same as the value passed +as the callback's first argument. +Reading is initially enabled, and returning <c>false</c> does not +imply there cannot be subsequent <c>recv</c> callbacks since +messages may already have been read. +An empty tail is equivalent to the prevailing callback. +Defaults to a callback equivalent to <c>fun(ack, _) -> []; (_, Msg) -> +[Msg] end</c>.</p> + <p> Remaining options are any accepted by &ssl_connect3; or &gen_tcp_connect3; for diff --git a/lib/diameter/doc/src/files.mk b/lib/diameter/doc/src/files.mk index cb4f88a375..4c1297f6cc 100644 --- a/lib/diameter/doc/src/files.mk +++ b/lib/diameter/doc/src/files.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2016. All Rights Reserved. +# Copyright Ericsson AB 2010-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -40,8 +40,7 @@ XML_PART_FILES = \ user_man.xml XML_EXTRA_FILES = \ - seealso.ent \ - diameter_soc_rfc6733.xml + seealso.ent XML_CHAPTER_FILES = \ diameter_intro.xml \ diff --git a/lib/erl_docgen/src/erl_docgen.app.src b/lib/erl_docgen/src/erl_docgen.app.src index d63d880d89..171c697585 100644 --- a/lib/erl_docgen/src/erl_docgen.app.src +++ b/lib/erl_docgen/src/erl_docgen.app.src @@ -9,6 +9,6 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["xmerl-1.3.7","stdlib-2.5","edoc-0.7.13","erts-6.0"]} + {runtime_dependencies, ["xmerl-1.3.7","stdlib-3.4","edoc-0.7.13","erts-9.0"]} ] }. diff --git a/lib/et/src/et.app.src b/lib/et/src/et.app.src index 7a5928d6ab..f4e32f734d 100644 --- a/lib/et/src/et.app.src +++ b/lib/et/src/et.app.src @@ -33,6 +33,6 @@ {registered, [et_collector]}, {applications, [stdlib, kernel]}, {env, []}, - {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.10", - "kernel-3.0","erts-8.0"]} + {runtime_dependencies, ["wx-1.2","stdlib-3.4","runtime_tools-1.10", + "kernel-5.3","erts-9.0"]} ]}. diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src index b4ff6c9242..cc75a0f790 100644 --- a/lib/eunit/src/eunit.app.src +++ b/lib/eunit/src/eunit.app.src @@ -19,4 +19,4 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["stdlib-2.5","kernel-3.0","erts-6.0"]}]}. + {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}. diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src index 3c3a1004f1..5b2280594f 100644 --- a/lib/hipe/main/hipe.app.src +++ b/lib/hipe/main/hipe.app.src @@ -235,5 +235,5 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.5","kernel-3.0", + {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-3.4","kernel-5.3", "erts-9.0","compiler-5.0"]}]}. diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 480db6814e..2887014c1c 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -378,16 +378,11 @@ df(Mod, Func, Arity) when is_atom(Mod), is_atom(Func) -> catch _:_ -> {undef,Mod} end. -dff(File, Fs) when is_pid(File), is_list(Fs) -> - lists:foreach(fun(Mfa) -> - disassemble_function(File, Mfa), - io:nl(File) - end, Fs); -dff(Name, Fs) when is_list(Name) -> - case file:open(Name, [write]) of +dff(Name, Fs) -> + case file:open(Name, [write,raw,delayed_write]) of {ok,F} -> try - dff(F, Fs) + dff_1(F, Fs) after _ = file:close(F) end; @@ -395,12 +390,18 @@ dff(Name, Fs) when is_list(Name) -> {error,{badopen,Reason}} end. +dff_1(File, Fs) -> + lists:foreach(fun(Mfa) -> + disassemble_function(File, Mfa), + file:write(File, "\n") + end, Fs). + disassemble_function(File, {_,_,_}=MFA) -> cont_dis(File, erts_debug:disassemble(MFA), MFA). cont_dis(_, false, _) -> ok; cont_dis(File, {Addr,Str,MFA}, MFA) -> - io:put_chars(File, binary_to_list(Str)), + ok = file:write(File, Str), cont_dis(File, erts_debug:disassemble(Addr), MFA); cont_dis(_, {_,_,_}, _) -> ok. diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl index 90e49ddfdf..49aa5f8bda 100644 --- a/lib/kernel/src/inet_res.erl +++ b/lib/kernel/src/inet_res.erl @@ -859,15 +859,17 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, {ok,S} -> Timeout = inet:timeout( (Tm * (1 bsl I)) div Retry, Timer), - {S, case query_udp( S, Id, Buffer, IP, Port, Timeout, Verbose) of {ok,#dns_rec{header=H}} when H#dns_header.tc -> TcpTimeout = inet:timeout(Tm*5, Timer), - query_tcp( - TcpTimeout, Id, Buffer, IP, Port, Verbose); - Reply -> Reply - end}; + {S, query_tcp( + TcpTimeout, Id, Buffer, IP, Port, Verbose)}; + {error, econnrefused} = Err -> + ok = udp_close(S), + {#sock{}, Err}; + Reply -> {S, Reply} + end; Error -> {S0,Error} end diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 2a11b04310..2a88cc7e26 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -120,6 +120,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-9.1", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.1", "stdlib-3.4", "sasl-3.0"]} ] }. diff --git a/lib/mnesia/src/mnesia.app.src b/lib/mnesia/src/mnesia.app.src index 6b49fc6c88..c755b4d4b9 100644 --- a/lib/mnesia/src/mnesia.app.src +++ b/lib/mnesia/src/mnesia.app.src @@ -49,4 +49,4 @@ ]}, {applications, [kernel, stdlib]}, {mod, {mnesia_app, []}}, - {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-7.0"]}]}. + {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}. diff --git a/lib/observer/priv/bin/cdv b/lib/observer/priv/bin/cdv index d14fd47e41..2a509c16af 100755 --- a/lib/observer/priv/bin/cdv +++ b/lib/observer/priv/bin/cdv @@ -1,4 +1,4 @@ #!/bin/sh -erl -noinput -s crashdump_viewer script_start $@ +erl -env ERL_CRASH_DUMP_SECONDS 0 -noinput -s crashdump_viewer script_start $@ diff --git a/lib/observer/priv/bin/cdv.bat b/lib/observer/priv/bin/cdv.bat index 18136a30d6..fa87c08adf 100644 --- a/lib/observer/priv/bin/cdv.bat +++ b/lib/observer/priv/bin/cdv.bat @@ -1,2 +1,2 @@ @ECHO OFF -CALL werl -s crashdump_viewer script_start %* +CALL werl -env ERL_CRASH_DUMP_SECONDS 0 -s crashdump_viewer script_start %* diff --git a/lib/observer/src/cdv_detail_wx.erl b/lib/observer/src/cdv_detail_wx.erl index 4c26e447a6..f6d282638a 100644 --- a/lib/observer/src/cdv_detail_wx.erl +++ b/lib/observer/src/cdv_detail_wx.erl @@ -20,7 +20,7 @@ -behaviour(wx_object). --export([start_link/4]). +-export([start_link/5]). -export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3, handle_call/3, handle_info/2]). @@ -39,27 +39,42 @@ -define(ID_NOTEBOOK, 604). %% Detail view -start_link(Id, Data, ParentFrame, Callback) -> - wx_object:start_link(?MODULE, [Id, Data, ParentFrame, Callback, self()], []). +start_link(Id, Data, ParentFrame, Callback, App) -> + wx_object:start_link(?MODULE,[Id,Data,ParentFrame,Callback,App,self()],[]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -init([Id, Data, ParentFrame, Callback, Parent]) -> +init([Id, Data, ParentFrame, Callback, App, Parent]) -> + display_progress(ParentFrame,App), case Callback:get_details(Id, Data) of {ok,Details} -> - init(Id,ParentFrame,Callback,Parent,Details); + init(Id,ParentFrame,Callback,App,Parent,Details); {yes_no, Info, Fun} -> + destroy_progress(App), case observer_lib:display_yes_no_dialog(Info) of ?wxID_YES -> Fun(); ?wxID_NO -> ok end, {stop,normal}; {info,Info} -> + destroy_progress(App), observer_lib:display_info_dialog(ParentFrame,Info), {stop,normal} end. -init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) -> +%% Display progress bar only if the calling app is crashdump_viewer +display_progress(ParentFrame,cdv) -> + observer_lib:display_progress_dialog(ParentFrame, + "Crashdump Viewer", + "Reading data"); +display_progress(_,_) -> + ok. +destroy_progress(cdv) -> + observer_lib:destroy_progress_dialog(); +destroy_progress(_) -> + ok. + +init(Id,ParentFrame,Callback,App,Parent,{Title,Info,TW}) -> Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [Title], [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]), MenuBar = wxMenuBar:new(), @@ -88,6 +103,7 @@ init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) -> wxFrame:connect(Frame, close_window), wxMenu:connect(Frame, command_menu_selected), wxFrame:show(Frame), + destroy_progress(App), {Frame, #state{parent=Parent, id=Id, frame=Frame, diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl index 5158e95a65..4b43b6a840 100644 --- a/lib/observer/src/cdv_html_wx.erl +++ b/lib/observer/src/cdv_html_wx.erl @@ -52,8 +52,12 @@ init([ParentWin, HtmlText]) -> init(ParentWin, HtmlText, undefined, cdv). init(ParentWin, HtmlText, Tab, App) -> + %% If progress dialog is shown, remove it now - and sett cursor busy instead + observer_lib:destroy_progress_dialog(), + wx_misc:beginBusyCursor(), HtmlWin = observer_lib:html_window(ParentWin), wxHtmlWindow:setPage(HtmlWin,HtmlText), + wx_misc:endBusyCursor(), {HtmlWin, #state{panel=HtmlWin,expand_table=Tab,app=App}}. %%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -123,11 +127,12 @@ handle_event(Event, State) -> %%%----------------------------------------------------------------- %%% Internal -expand(Id,Callback,#state{expand_wins=Opened0}=State) -> +expand(Id,Callback,#state{expand_wins=Opened0, app=App}=State) -> Opened = case lists:keyfind(Id,1,Opened0) of false -> - EW = cdv_detail_wx:start_link(Id,[],State#state.panel,Callback), + EW = cdv_detail_wx:start_link(Id,[],State#state.panel, + Callback,App), wx_object:get_pid(EW) ! active, [{Id,EW}|Opened0]; {_,EW} -> diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl index f206d7e4c9..bdcb13f22d 100644 --- a/lib/observer/src/cdv_term_cb.erl +++ b/lib/observer/src/cdv_term_cb.erl @@ -30,23 +30,31 @@ detail_pages() -> [{"Term", fun init_term_page/2}]. init_term_page(ParentWin, {Type, [Term, Tab]}) -> + observer_lib:report_progress({ok,"Expanding term"}), + observer_lib:report_progress({ok,start_pulse}), Expanded = expand(Term, true), BinSaved = expand(Term, Tab), + observer_lib:report_progress({ok,stop_pulse}), cdv_multi_wx:start_link( ParentWin, [{"Format \~p",cdv_html_wx,{Type, format_term_fun("~p",BinSaved,Tab)}}, {"Format \~tp",cdv_html_wx,{Type,format_term_fun("~tp",BinSaved,Tab)}}, {"Format \~w",cdv_html_wx,{Type,format_term_fun("~w",BinSaved,Tab)}}, + {"Format \~tw",cdv_html_wx,{Type,format_term_fun("~tw",BinSaved,Tab)}}, {"Format \~s",cdv_html_wx,{Type,format_term_fun("~s",Expanded,Tab)}}, {"Format \~ts",cdv_html_wx,{Type,format_term_fun("~ts",Expanded,Tab)}}]). format_term_fun(Format,Term,Tab) -> fun() -> + observer_lib:report_progress({ok,"Formatting term"}), + observer_lib:report_progress({ok,start_pulse}), try io_lib:format(Format,[Term]) of Str -> {expand, plain_html(Str), Tab} catch error:badarg -> Warning = "This term can not be formatted with " ++ Format, observer_html_lib:warning(Warning) + after + observer_lib:report_progress({ok,stop_pulse}) end end. diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl index f3daae8e4d..33c0c880b1 100644 --- a/lib/observer/src/cdv_virtual_list_wx.erl +++ b/lib/observer/src/cdv_virtual_list_wx.erl @@ -174,7 +174,7 @@ do_start_detail_win(Id, #state{panel=Panel,detail_wins=Opened, case lists:keyfind(Id, 1, Opened) of false -> Data = call(Holder, {get_data, self(), Id}), - case cdv_detail_wx:start_link(Id, Data, Panel, Callback) of + case cdv_detail_wx:start_link(Id, Data, Panel, Callback, cdv) of {error, _} -> Opened; IW -> [{Id, IW} | Opened] end; diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl index 8cc135d174..0e33c9e618 100644 --- a/lib/observer/src/cdv_wx.erl +++ b/lib/observer/src/cdv_wx.erl @@ -413,7 +413,16 @@ load_dump(Frame,undefined) -> error end; load_dump(Frame,FileName) -> - ok = observer_lib:display_progress_dialog("Crashdump Viewer", + case maybe_warn_filename(FileName) of + continue -> + do_load_dump(Frame,FileName); + stop -> + error + end. + +do_load_dump(Frame,FileName) -> + ok = observer_lib:display_progress_dialog(wx:null(), + "Crashdump Viewer", "Loading crashdump"), crashdump_viewer:read_file(FileName), case observer_lib:wait_for_progress() of @@ -433,6 +442,33 @@ load_dump(Frame,FileName) -> error end. +maybe_warn_filename(FileName) -> + case os:getenv("ERL_CRASH_DUMP_SECONDS")=="0" orelse + os:getenv("ERL_CRASH_DUMP_BYTES")=="0" of + true -> + continue; + false -> + DumpName = case os:getenv("ERL_CRASH_DUMP") of + false -> filename:absname("erl_crash.dump"); + Name -> filename:absname(Name) + end, + case filename:absname(FileName) of + DumpName -> + Warning = + "WARNING: the current crashdump might be overwritten " + "if the crashdump_viewer node crashes.\n\n" + "Renaming the file before inspecting it will " + "remove the problem.\n\n" + "Do you want to continue?", + case observer_lib:display_yes_no_dialog(Warning) of + ?wxID_YES -> continue; + ?wxID_NO -> stop + end; + _ -> + continue + end + end. + %%%----------------------------------------------------------------- %%% Find help document (HTML files) get_help_doc(HelpId) -> diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index 31258cdf20..51ff69fd69 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -36,7 +36,6 @@ %% file: The name of the crashdump currently viewed. %% dump_vsn: The version number of the crashdump %% wordsize: 4 | 8, the number of bytes in a word. -%% binaries: a gb_tree containing binaries or links to binaries in the dump %% %% User API @@ -87,6 +86,7 @@ -define(max_line_size,100). % max number of bytes (i.e. characters) the % line_head/1 function can return -define(not_available,"N/A"). +-define(binary_size_progress_limit,10000). %% All possible tags - use macros in order to avoid misspelling in the code @@ -106,6 +106,8 @@ -define(internal_ets,internal_ets). -define(loaded_modules,loaded_modules). -define(memory,memory). +-define(memory_map,memory_map). +-define(memory_status,memory_status). -define(mod,mod). -define(no_distribution,no_distribution). -define(node,node). @@ -122,7 +124,7 @@ -define(visible_node,visible_node). --record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown",binaries}). +-record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown"}). %%%----------------------------------------------------------------- %%% Debugging @@ -203,7 +205,8 @@ do_script_start(StartFun) -> io:format("\ncdv crash: ~tp\n",[Reason]) end; _ -> - io:format("\ncdv crash: ~p\n",[unknown_reason]) + %io:format("\ncdv crash: ~p\n",[unknown_reason]) + ok end; Error -> io:format("\ncdv start failed: ~tp\n",[Error]) @@ -305,6 +308,8 @@ expand_binary(Pos) -> init([]) -> ets:new(cdv_dump_index_table,[ordered_set,named_table,public]), ets:new(cdv_reg_proc_table,[ordered_set,named_table,public]), + ets:new(cdv_binary_index_table,[ordered_set,named_table,public]), + ets:new(cdv_heap_file_chars,[ordered_set,named_table,public]), {ok, #state{}}. %%-------------------------------------------------------------------- @@ -348,9 +353,9 @@ handle_call(procs_summary,_From,State=#state{file=File,wordsize=WS}) -> Procs = procs_summary(File,WS), {reply,{ok,Procs,TW},State}; handle_call({proc_details,Pid},_From, - State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn,binaries=B})-> + State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn})-> Reply = - case get_proc_details(File,Pid,WS,DumpVsn,B) of + case get_proc_details(File,Pid,WS,DumpVsn) of {ok,Proc,TW} -> {ok,Proc,TW}; Other -> @@ -462,9 +467,9 @@ handle_call(schedulers,_From,State=#state{file=File}) -> %%-------------------------------------------------------------------- handle_cast({read_file,File}, _State) -> case do_read_file(File) of - {ok,Binaries,DumpVsn} -> + {ok,DumpVsn} -> observer_lib:report_progress({ok,done}), - {noreply, #state{file=File,binaries=Binaries,dump_vsn=DumpVsn}}; + {noreply, #state{file=File,dump_vsn=DumpVsn}}; Error -> end_progress(Error), {noreply, #state{}} @@ -746,32 +751,6 @@ get_rest_of_line_1(Fd, <<>>, Acc) -> eof -> {eof,lists:reverse(Acc)} end. -get_lines_to_empty(Fd) -> - case get_chunk(Fd) of - {ok,Bin} -> - get_lines_to_empty(Fd,Bin,[],[]); - eof -> - [] - end. -get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,[],Lines) -> - put_chunk(Fd,Bin), - lists:reverse(Lines); -get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]); -get_lines_to_empty(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,Acc,Lines); -get_lines_to_empty(Fd,<<$\s:8,Bin/binary>>,[],Lines) -> - get_lines_to_empty(Fd,Bin,[],Lines); -get_lines_to_empty(Fd,<<Char:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,[Char|Acc],Lines); -get_lines_to_empty(Fd,<<>>,Acc,Lines) -> - case get_chunk(Fd) of - {ok,Bin} -> - get_lines_to_empty(Fd,Bin,Acc,Lines); - eof -> - lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))]) - end. - split(Str) -> split($ ,Str,[]). split(Char,Str) -> @@ -817,18 +796,17 @@ do_read_file(File) -> {Tag,Id,Rest,N1} = tag(Fd,TagAndRest,1), case Tag of ?erl_crash_dump -> - reset_index_table(), + reset_tables(), insert_index(Tag,Id,N1+1), put_last_tag(Tag,""), - indexify(Fd,Rest,N1), + DumpVsn = [list_to_integer(L) || + L<-string:lexemes(Id,".")], + AddrAdj = get_bin_addr_adj(DumpVsn), + indexify(Fd,AddrAdj,Rest,N1), end_progress(), check_if_truncated(), - [{DumpVsn0,_}] = lookup_index(?erl_crash_dump), - DumpVsn = [list_to_integer(L) || - L<-string:lexemes(DumpVsn0,".")], - Binaries = read_binaries(Fd,DumpVsn), close(Fd), - {ok,Binaries,DumpVsn}; + {ok,DumpVsn}; _Other -> R = io_lib:format( "~ts is not an Erlang crash dump~n", @@ -856,15 +834,31 @@ do_read_file(File) -> {error,R} end. -indexify(Fd,Bin,N) -> +indexify(Fd,AddrAdj,Bin,N) -> case binary:match(Bin,<<"\n=">>) of {Start,Len} -> Pos = Start+Len, <<_:Pos/binary,TagAndRest/binary>> = Bin, {Tag,Id,Rest,N1} = tag(Fd,TagAndRest,N+Pos), - insert_index(Tag,Id,N1+1), % +1 to get past newline - put_last_tag(Tag,Id), - indexify(Fd,Rest,N1); + NewPos = N1+1, % +1 to get past newline + case Tag of + ?binary -> + %% Binaries are stored in a separate table in + %% order to minimize lookup time. Key is the + %% translated address. + {HexAddr,_} = get_hex(Id), + Addr = HexAddr bor AddrAdj, + insert_binary_index(Addr,NewPos); + _ -> + insert_index(Tag,Id,NewPos) + end, + case put_last_tag(Tag,Id) of + {?proc_heap,LastId} -> + [{_,LastPos}] = lookup_index(?proc_heap,LastId), + ets:insert(cdv_heap_file_chars,{LastId,N+Start+1-LastPos}); + _ -> ok + end, + indexify(Fd,AddrAdj,Rest,N1); nomatch -> case progress_read(Fd) of {ok,Chunk0} when is_binary(Chunk0) -> @@ -875,7 +869,7 @@ indexify(Fd,Bin,N) -> _ -> {Chunk0,N+byte_size(Bin)} end, - indexify(Fd,Chunk,N1); + indexify(Fd,AddrAdj,Chunk,N1); eof -> eof end @@ -911,7 +905,11 @@ check_if_truncated() -> find_truncated_proc(TruncatedTag) end. -find_truncated_proc({?atoms,_Id}) -> +find_truncated_proc({Tag,_Id}) when Tag==?atoms; + Tag==?binary; + Tag==?instr_data; + Tag==?memory_status; + Tag==?memory_map -> put(truncated_proc,false); find_truncated_proc({Tag,Pid}) -> case is_proc_tag(Tag) of @@ -1060,14 +1058,14 @@ procs_summary(File,WS) -> %%----------------------------------------------------------------- %% Page with one process -get_proc_details(File,Pid,WS,DumpVsn,Binaries) -> +get_proc_details(File,Pid,WS,DumpVsn) -> case lookup_index(?proc,Pid) of [{_,Start}] -> Fd = open(File), {{Stack,MsgQ,Dict},TW} = case truncated_warning([{?proc,Pid}]) of [] -> - {expand_memory(Fd,Pid,DumpVsn,Binaries),[]}; + {expand_memory(Fd,Pid,DumpVsn),[]}; TW0 -> {{[],[],[]},TW0} end, @@ -1176,7 +1174,7 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) -> get_procinfo(Fd,Fun,Proc#proc{old_heap_end=bytes(Fd)},WS); %% - END - moved from get_procinfo - "Last calls" -> - get_procinfo(Fd,Fun,Proc#proc{last_calls=get_lines_to_empty(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{last_calls=get_last_calls(Fd)},WS); "Link list" -> {Links,Monitors,MonitoredBy} = parse_link_list(bytes(Fd),[],[],[]), get_procinfo(Fd,Fun,Proc#proc{links=Links, @@ -1200,6 +1198,66 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) -> get_procinfo(Fd,Fun,Proc,WS) end. +%% The end of the 'Last calls' section is meant to be an empty line, +%% but in some cases this is not the case, so we also need to look for +%% the next heading which currently (OTP-20.1) can be "Link list: ", +%% "Dictionary: " or "Reductions: ". We do this by looking for ": " +%% and when found, pushing the heading back into the saved chunk. +%% +%% Note that the 'Last calls' section is only present if the +%% 'save_calls' process flag is set. +get_last_calls(Fd) -> + case get_chunk(Fd) of + {ok,Bin} -> + get_last_calls(Fd,Bin,[],[]); + eof -> + [] + end. +get_last_calls(Fd,<<$\n:8,Bin/binary>>,[],Lines) -> + %% Empty line - we're done + put_chunk(Fd,Bin), + lists:reverse(Lines); +get_last_calls(Fd,<<$::8>>,Acc,Lines) -> + case get_chunk(Fd) of + {ok,Bin} -> + %% Could be a colon followed by a space - see next function clause + get_last_calls(Fd,<<$::8,Bin/binary>>,Acc,Lines); + eof -> + %% Truncated here - either we've got the next heading, or + %% it was truncated in a last call function, in which case + %% we note that it was truncated + case byte_list_to_string(lists:reverse(Acc)) of + NextHeading when NextHeading=="Link list"; + NextHeading=="Dictionary"; + NextHeading=="Reductions" -> + put_chunk(Fd,list_to_binary(NextHeading++":")), + lists:reverse(Lines); + LastCallFunction-> + lists:reverse(Lines,[LastCallFunction++":...(truncated)"]) + end + end; +get_last_calls(Fd,<<$\::8,$\s:8,Bin/binary>>,Acc,Lines) -> + %% ": " - means we have the next heading in Acc - save it back + %% into the chunk and return the lines we've found + HeadingBin = list_to_binary(lists:reverse(Acc,[$:])), + put_chunk(Fd,<<HeadingBin/binary,Bin/binary>>), + lists:reverse(Lines); +get_last_calls(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]); +get_last_calls(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,Acc,Lines); +get_last_calls(Fd,<<$\s:8,Bin/binary>>,[],Lines) -> + get_last_calls(Fd,Bin,[],Lines); +get_last_calls(Fd,<<Char:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,[Char|Acc],Lines); +get_last_calls(Fd,<<>>,Acc,Lines) -> + case get_chunk(Fd) of + {ok,Bin} -> + get_last_calls(Fd,Bin,Acc,Lines); + eof -> + lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))]) + end. + parse_link_list([SB|Str],Links,Monitors,MonitoredBy) when SB==$[; SB==$] -> parse_link_list(Str,Links,Monitors,MonitoredBy); parse_link_list("#Port"++_=Str,Links,Monitors,MonitoredBy) -> @@ -1325,10 +1383,10 @@ maybe_other_node2(Channel) -> end. -expand_memory(Fd,Pid,DumpVsn,Binaries) -> +expand_memory(Fd,Pid,DumpVsn) -> BinAddrAdj = get_bin_addr_adj(DumpVsn), put(fd,Fd), - Dict = read_heap(Fd,Pid,BinAddrAdj,Binaries), + Dict = read_heap(Fd,Pid,BinAddrAdj,gb_trees:empty()), Expanded = {read_stack_dump(Fd,Pid,BinAddrAdj,Dict), read_messages(Fd,Pid,BinAddrAdj,Dict), read_dictionary(Fd,Pid,BinAddrAdj,Dict)}, @@ -1346,25 +1404,6 @@ get_bin_addr_adj(_) -> 0. %%% -%%% Read binaries. -%%% -read_binaries(Fd,DumpVsn) -> - AllBinaries = lookup_index(?binary), - AddrAdj = get_bin_addr_adj(DumpVsn), - Fun = fun({Addr0,Pos},Dict0) -> - pos_bof(Fd,Pos), - {HexAddr,_} = get_hex(Addr0), - Addr = HexAddr bor AddrAdj, - Bin = - case line_head(Fd) of - {eof,_} -> '#CDVTruncatedBinary'; - _Size -> {'#CDVBin',Pos} - end, - gb_trees:enter(Addr,Bin,Dict0) - end, - progress_foldl("Processing binaries",Fun,gb_trees:empty(),AllBinaries). - -%%% %%% Read top level section. %%% @@ -1454,6 +1493,8 @@ parse_dictionary(Line0, BinAddrAdj, D) -> read_heap(Fd,Pid,BinAddrAdj,Dict0) -> case lookup_index(?proc_heap,Pid) of [{_,Pos}] -> + [{_,Chars}] = ets:lookup(cdv_heap_file_chars,Pid), + init_progress("Reading process heap",Chars), pos_bof(Fd,Pos), read_heap(BinAddrAdj,Dict0); [] -> @@ -1464,13 +1505,16 @@ read_heap(BinAddrAdj,Dict0) -> %% This function is never called if the dump is truncated in {?proc_heap,Pid} case get(fd) of end_of_heap -> + end_progress(), Dict0; Fd -> case bytes(Fd) of "=" ++ _next_tag -> + end_progress(), put(fd, end_of_heap), Dict0; Line -> + update_progress(length(Line)+1), Dict = parse(Line,BinAddrAdj,Dict0), read_heap(BinAddrAdj,Dict) end @@ -2526,9 +2570,9 @@ parse_heap_term("Yc"++Line0, Addr, BinAddrAdj, D0) -> %Reference-counted binary. {Offset,":"++Line2} = get_hex(Line1), {Sz,Line} = get_hex(Line2), Binp = Binp0 bor BinAddrAdj, - Term = case gb_trees:lookup(Binp, D0) of - {value,Bin} -> cdvbin(Offset,Sz,Bin); - none -> '#CDVNonexistingBinary' + Term = case lookup_binary_index(Binp) of + [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start}); + [] -> '#CDVNonexistingBinary' end, D = gb_trees:insert(Addr, Term, D0), {Term,Line,D}; @@ -2537,15 +2581,14 @@ parse_heap_term("Ys"++Line0, Addr, BinAddrAdj, D0) -> %Sub binary. {Offset,":"++Line2} = get_hex(Line1), {Sz,Line} = get_hex(Line2), Binp = Binp0 bor BinAddrAdj, - Term = case gb_trees:lookup(Binp, D0) of - {value,Bin} -> cdvbin(Offset,Sz,Bin); - none when Binp0=/=Binp -> + Term = case lookup_binary_index(Binp) of + [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start}); + [] -> %% Might it be on the heap? - case gb_trees:lookup(Binp0, D0) of + case gb_trees:lookup(Binp, D0) of {value,Bin} -> cdvbin(Offset,Sz,Bin); none -> '#CDVNonexistingBinary' - end; - none -> '#CDVNonexistingBinary' + end end, D = gb_trees:insert(Addr, Term, D0), {Term,Line,D}. @@ -2636,6 +2679,7 @@ deref_ptr(Ptr, Line, BinAddrAdj, D0) -> put(fd, end_of_heap), deref_ptr(Ptr, Line, BinAddrAdj, D0); L -> + update_progress(length(L)+1), D = parse(L, BinAddrAdj, D0), deref_ptr(Ptr, Line, BinAddrAdj, D) end @@ -2701,19 +2745,33 @@ get_label([H|T], Acc) -> get_label(T, [H|Acc]). get_binary(Line0) -> - {N,":"++Line} = get_hex(Line0), - do_get_binary(N, Line, []). + case get_hex(Line0) of + {N,":"++Line} -> + do_get_binary(N, Line, [], false); + _ -> + {'#CDVTruncatedBinary',[]} + end. get_binary(Offset,Size,Line0) -> - {_N,":"++Line} = get_hex(Line0), - do_get_binary(Size, lists:sublist(Line,(Offset*2)+1,Size*2), []). - -do_get_binary(0, Line, Acc) -> + case get_hex(Line0) of + {_N,":"++Line} -> + Progress = Size>?binary_size_progress_limit, + Progress andalso init_progress("Reading binary",Size), + do_get_binary(Size, lists:sublist(Line,(Offset*2)+1,Size*2), [], + Progress); + _ -> + {'#CDVTruncatedBinary',[]} + end. + +do_get_binary(0, Line, Acc, Progress) -> + Progress andalso end_progress(), {list_to_binary(lists:reverse(Acc)),Line}; -do_get_binary(N, [A,B|Line], Acc) -> +do_get_binary(N, [A,B|Line], Acc, Progress) -> Byte = (get_hex_digit(A) bsl 4) bor get_hex_digit(B), - do_get_binary(N-1, Line, [Byte|Acc]); -do_get_binary(_N, [], _Acc) -> + Progress andalso update_progress(), + do_get_binary(N-1, Line, [Byte|Acc], Progress); +do_get_binary(_N, [], _Acc, Progress) -> + Progress andalso end_progress(), {'#CDVTruncatedBinary',[]}. cdvbin(Offset,Size,{'#CDVBin',Pos}) -> @@ -2721,12 +2779,17 @@ cdvbin(Offset,Size,{'#CDVBin',Pos}) -> cdvbin(Offset,Size,['#CDVBin',_,_,Pos]) -> ['#CDVBin',Offset,Size,Pos]; cdvbin(_,_,'#CDVTruncatedBinary') -> - '#CDVTruncatedBinary'. + '#CDVTruncatedBinary'; +cdvbin(_,_,'#CDVNonexistingBinary') -> + '#CDVNonexistingBinary'. %%----------------------------------------------------------------- -%% Functions for accessing the cdv_dump_index_table -reset_index_table() -> - ets:delete_all_objects(cdv_dump_index_table). +%% Functions for accessing tables +reset_tables() -> + ets:delete_all_objects(cdv_dump_index_table), + ets:delete_all_objects(cdv_reg_proc_table), + ets:delete_all_objects(cdv_binary_index_table), + ets:delete_all_objects(cdv_heap_file_chars). insert_index(Tag,Id,Pos) -> ets:insert(cdv_dump_index_table,{{Tag,Pos},Id}). @@ -2741,6 +2804,11 @@ lookup_index(Tag,Id) -> count_index(Tag) -> ets:select_count(cdv_dump_index_table,[{{{Tag,'_'},'_'},[],[true]}]). +insert_binary_index(Addr,Pos) -> + ets:insert(cdv_binary_index_table,{Addr,Pos}). + +lookup_binary_index(Addr) -> + ets:lookup(cdv_binary_index_table,Addr). %%----------------------------------------------------------------- %% Convert tags read from crashdump to atoms used as first part of key @@ -2811,23 +2879,6 @@ to_value_list(Record) -> Values. %%%----------------------------------------------------------------- -%%% Fold over List and report progress in percent. -%%% Report is the text to be presented in the progress dialog. -%%% Acc0 is the initial accumulator and will be passed to Fun as the -%%% second arguement, i.e. Fun = fun(Item,Acc) -> NewAcc end. -progress_foldl(Report,Fun,Acc0,List) -> - init_progress(Report, length(List)), - progress_foldl1(Fun,Acc0,List). - -progress_foldl1(Fun,Acc,[H|T]) -> - update_progress(), - progress_foldl1(Fun,Fun(H,Acc),T); -progress_foldl1(_Fun,Acc,[]) -> - end_progress(), - Acc. - - -%%%----------------------------------------------------------------- %%% Map over List and report progress in percent. %%% Report is the text to be presented in the progress dialog. %%% Distribute the load over a number of processes, and File is opened diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src index 3a5bd172e7..f682e3dc7b 100644 --- a/lib/observer/src/observer.app.src +++ b/lib/observer/src/observer.app.src @@ -65,7 +65,7 @@ {registered, []}, {applications, [kernel, stdlib]}, {env, []}, - {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.8.14", + {runtime_dependencies, ["wx-1.2","stdlib-3.4","runtime_tools-1.8.14", "kernel-3.0","inets-5.10","et-1.5", "erts-7.0"]}]}. diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl index 92fc7cec92..68381bcc7b 100644 --- a/lib/observer/src/observer_html_lib.erl +++ b/lib/observer/src/observer_html_lib.erl @@ -337,17 +337,24 @@ href_proc_bin(From, T, Acc, LTB) -> Size = list_to_integer(SizeStr), PreviewSize = min(Size,10), Id = {list_to_integer(Offset),PreviewSize,list_to_integer(Pos)}, - {ok,PreviewBin} = crashdump_viewer:expand_binary(Id), - PreviewStr = preview_string(Size, PreviewBin), - if LTB -> - href("TARGET=\"expanded\"", - ["#Binary?offset="++Offset++ - "&size="++SizeStr++ - "&pos="++Pos], - PreviewStr); - true -> - PreviewStr - end; + case crashdump_viewer:expand_binary(Id) of + {ok, '#CDVTruncatedBinary'} -> + lists:flatten( + "<FONT COLOR=\"#FF0000\">" + "<<...(Truncated Binary)>>" + "</FONT>"); + {ok, PreviewBin} -> + PreviewStr = preview_string(Size, PreviewBin), + if LTB -> + href("TARGET=\"expanded\"", + ["#Binary?offset="++Offset++ + "&size="++SizeStr++ + "&pos="++Pos], + PreviewStr); + true -> + PreviewStr + end + end; [PreviewIntStr,SizeStr,Md5] when From =:= obs -> Size = list_to_integer(SizeStr), PreviewInt = list_to_integer(PreviewIntStr), diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl index 658adf1c4a..e5ffe61d25 100644 --- a/lib/observer/src/observer_lib.erl +++ b/lib/observer/src/observer_lib.erl @@ -21,7 +21,7 @@ -export([get_wx_parent/1, display_info_dialog/2, display_yes_no_dialog/1, - display_progress_dialog/2, destroy_progress_dialog/0, + display_progress_dialog/3, destroy_progress_dialog/0, wait_for_progress/0, report_progress/1, user_term/3, user_term_multiline/3, interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1, @@ -40,6 +40,7 @@ -define(SINGLE_LINE_STYLE, ?wxBORDER_NONE bor ?wxTE_READONLY bor ?wxTE_RICH2). -define(MULTI_LINE_STYLE, ?SINGLE_LINE_STYLE bor ?wxTE_MULTILINE). +-define(pulse_timeout,50). get_wx_parent(Window) -> Parent = wxWindow:getParent(Window), @@ -688,11 +689,11 @@ create_status_bar(Panel) -> %%%----------------------------------------------------------------- %%% Progress dialog -define(progress_handler,cdv_progress_handler). -display_progress_dialog(Title,Str) -> +display_progress_dialog(Parent,Title,Str) -> Caller = self(), Env = wx:get_env(), spawn_link(fun() -> - progress_handler(Caller,Env,Title,Str) + progress_handler(Caller,Env,Parent,Title,Str) end), ok. @@ -716,31 +717,38 @@ report_progress(Progress) -> ok end. -progress_handler(Caller,Env,Title,Str) -> +progress_handler(Caller,Env,Parent,Title,Str) -> register(?progress_handler,self()), wx:set_env(Env), - PD = progress_dialog(Env,Title,Str), - try progress_loop(Title,PD,Caller) + PD = progress_dialog(Env,Parent,Title,Str), + try progress_loop(Title,PD,Caller,infinity) catch closed -> normal end. -progress_loop(Title,PD,Caller) -> +progress_loop(Title,PD,Caller,Pulse) -> receive {progress,{ok,done}} -> % to make wait_for_progress/0 return Caller ! continue, - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); + {progress,{ok,start_pulse}} -> + update_progress_pulse(PD), + progress_loop(Title,PD,Caller,?pulse_timeout); + {progress,{ok,stop_pulse}} -> + progress_loop(Title,PD,Caller,infinity); {progress,{ok,Percent}} when is_integer(Percent) -> update_progress(PD,Percent), - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); {progress,{ok,Msg}} -> update_progress_text(PD,Msg), - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); {progress,{error, Reason}} -> + {Dialog,_,_} = PD, + Parent = wxWindow:getParent(Dialog), finish_progress(PD), FailMsg = if is_list(Reason) -> Reason; true -> file:format_error(Reason) end, - display_info_dialog(PD,"Crashdump Viewer Error",FailMsg), + display_info_dialog(Parent,"Crashdump Viewer Error",FailMsg), Caller ! error, unregister(?progress_handler), unlink(Caller); @@ -748,28 +756,57 @@ progress_loop(Title,PD,Caller) -> finish_progress(PD), unregister(?progress_handler), unlink(Caller) + after Pulse -> + update_progress_pulse(PD), + progress_loop(Title,PD,Caller,?pulse_timeout) end. -progress_dialog(_Env,Title,Str) -> - PD = wxProgressDialog:new(Title,Str, - [{maximum,101}, - {style, - ?wxPD_APP_MODAL bor - ?wxPD_SMOOTH bor - ?wxPD_AUTO_HIDE}]), - wxProgressDialog:setMinSize(PD,{200,-1}), - PD. +progress_dialog(_Env,Parent,Title,Str) -> + progress_dialog_new(Parent,Title,Str). update_progress(PD,Value) -> - try wxProgressDialog:update(PD,Value) + try progress_dialog_update(PD,Value) catch _:_ -> throw(closed) %% Port or window have died end. update_progress_text(PD,Text) -> - try wxProgressDialog:update(PD,0,[{newmsg,Text}]) + try progress_dialog_update(PD,Text) + catch _:_ -> throw(closed) %% Port or window have died + end. +update_progress_pulse(PD) -> + try progress_dialog_pulse(PD) catch _:_ -> throw(closed) %% Port or window have died end. finish_progress(PD) -> - wxProgressDialog:destroy(PD). + try progress_dialog_update(PD,100) + catch _:_ -> ok + after progress_dialog_destroy(PD) + end. + +progress_dialog_new(Parent,Title,Str) -> + Dialog = wxDialog:new(Parent, ?wxID_ANY, Title, + [{style,?wxDEFAULT_DIALOG_STYLE}]), + Panel = wxPanel:new(Dialog), + Sizer = wxBoxSizer:new(?wxVERTICAL), + Message = wxStaticText:new(Panel, 1, Str), + Gauge = wxGauge:new(Panel, 2, 100, [{size, {170, -1}}, + {style, ?wxGA_HORIZONTAL}]), + SizerFlags = ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT bor ?wxTOP, + wxSizer:add(Sizer, Message, [{flag,SizerFlags},{border,15}]), + wxSizer:add(Sizer, Gauge, [{flag, SizerFlags bor ?wxBOTTOM},{border,15}]), + wxPanel:setSizer(Panel, Sizer), + wxSizer:setSizeHints(Sizer, Dialog), + wxDialog:show(Dialog), + {Dialog,Message,Gauge}. + +progress_dialog_update({_,_,Gauge},Value) when is_integer(Value) -> + wxGauge:setValue(Gauge,Value); +progress_dialog_update({_,Message,Gauge},Text) when is_list(Text) -> + wxGauge:setValue(Gauge,0), + wxStaticText:setLabel(Message,Text). +progress_dialog_pulse({_,_,Gauge}) -> + wxGauge:pulse(Gauge). +progress_dialog_destroy({Dialog,_,_}) -> + wxDialog:destroy(Dialog). make_obsbin(Bin,Tab) -> Size = byte_size(Bin), diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl index d1665cec06..4ce38e439d 100644 --- a/lib/observer/src/observer_procinfo.erl +++ b/lib/observer/src/observer_procinfo.erl @@ -151,7 +151,7 @@ handle_event(#wx{event=#wxHtmlLink{linkInfo=#wxHtmlLinkInfo{href=Href}}}, Opened = case lists:keyfind(Id,1,Opened0) of false -> - Win = cdv_detail_wx:start_link(Id,[],Frame,Callback), + Win = cdv_detail_wx:start_link(Id,[],Frame,Callback,obs), [{Id,Win}|Opened0]; {_,Win} -> wxFrame:raise(Win), diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile index fcb1b73911..a44e54fc52 100644 --- a/lib/observer/test/Makefile +++ b/lib/observer/test/Makefile @@ -47,7 +47,7 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test # FLAGS # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += +nowarn_export_all +ERL_COMPILE_FLAGS += +warnings_as_errors +nowarn_export_all EBIN = . diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 77cf086d4b..f9ac884743 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -76,7 +76,7 @@ end_per_testcase(Case, Config) -> end, ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> []. all() -> [start_stop, @@ -364,6 +364,9 @@ special(File,Procs) -> crashdump_viewer:expand_binary({SOffset,SSize,SPos}), io:format(" expand binary ok",[]), + #proc{last_calls=LastCalls} = ProcDetails, + true = length(LastCalls) =< 4, + ['#CDVPid',X1,Y1,Z1] = proplists:get_value(ext_pid,Dict), ChannelStr1 = integer_to_list(X1), ExtPid = @@ -413,19 +416,90 @@ special(File,Procs) -> old_attrib=undefined, old_comp_info=undefined}=Mod2, ok; - %% ".strangemodname" -> - %% {ok,Mods,[]} = crashdump_viewer:loaded_modules(), - %% lookat_all_mods(Mods), - %% ok; - %% ".sort" -> - %% %% sort ports, atoms and modules ???? - %% ok; - %% ".trunc" -> - %% %% ???? - %% ok; - ".trunc.bytes" -> + ".trunc_bin1" -> + %% This is 'full_dist' truncated after the first + %% "=binary:" + %% i.e. no binary exist in the dump + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + '#CDVNonexistingBinary' = proplists:get_value(bin,Dict), + '#CDVNonexistingBinary' = proplists:get_value(sub_bin,Dict), + + io:format(" nonexisting binaries ok",[]), + ok; + ".trunc_bin2" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size" + %% i.e. binaries are truncated + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + + io:format(" expand truncated binary ok",[]), + ok; + ".trunc_bin3" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size:" + %% i.e. same as 'trunc_bin2', except the colon exists also + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + + io:format(" expand truncated binary ok",[]), + ok; + ".trunc_bin4" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size:BinaryMissinOneByte" + %% i.e. the full binary is truncated, but the sub binary is complete + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + io:format(" expand truncated binary ok",[]), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,<<_:SSize/binary>>} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + io:format(" expand complete sub binary ok",[]), + + ok; + ".trunc_bytes" -> {ok,_,[TW]} = crashdump_viewer:general_info(), {match,_} = re:run(TW,"CRASH DUMP SIZE LIMIT REACHED"), + io:format(" size limit information ok",[]), ok; ".unicode" -> #proc{pid=Pid0} = @@ -500,16 +574,45 @@ do_create_dumps(DataDir,Rel) -> current -> CD3 = dump_with_args(DataDir,Rel,"instr","+Mim true"), CD4 = dump_with_strange_module_name(DataDir,Rel,"strangemodname"), - Bytes = rand:uniform(300000) + 100, - CD5 = dump_with_args(DataDir,Rel,"trunc.bytes", + Tmp = dump_with_args(DataDir,Rel,"trunc_bytes",""), + {ok,#file_info{size=Max}} = file:read_file_info(Tmp), + ok = file:delete(Tmp), + Bytes = max(15,rand:uniform(Max)), + CD5 = dump_with_args(DataDir,Rel,"trunc_bytes", "-env ERL_CRASH_DUMP_BYTES " ++ integer_to_list(Bytes)), CD6 = dump_with_unicode_atoms(DataDir,Rel,"unicode"), - {[CD1,CD2,CD3,CD4,CD5,CD6], DosDump}; + TruncatedDumps = truncate_dump(CD1), + {[CD1,CD2,CD3,CD4,CD5,CD6|TruncatedDumps], DosDump}; _ -> {[CD1,CD2], DosDump} end. +truncate_dump(File) -> + {ok,Bin} = file:read_file(File), + BinTag = <<"\n=binary:">>, + Colon = <<":">>, + NewLine = case os:type() of + {win32,_} -> <<"\r\n">>; + _ -> <<"\n">> + end, + [StartBin,AfterTag] = binary:split(Bin,BinTag), + [AddrAndSize,BinaryAndRest] = binary:split(AfterTag,Colon), + [Binary,_Rest] = binary:split(BinaryAndRest,NewLine), + TruncSize = byte_size(Binary) - 2, + <<TruncBinary:TruncSize/binary,_/binary>> = Binary, + TruncName = filename:rootname(File) ++ ".trunc_bin", + write_trunc_files(TruncName,StartBin, + [BinTag,AddrAndSize,Colon,TruncBinary],1). + +write_trunc_files(TruncName0,Bin,[Part|Parts],N) -> + TruncName = TruncName0++integer_to_list(N), + Bin1 = <<Bin/binary,Part/binary>>, + ok = file:write_file(TruncName,Bin1), + [TruncName|write_trunc_files(TruncName0,Bin1,Parts,N+1)]; +write_trunc_files(_,_,[],_) -> + []. + %% Create a dump which has three visible nodes, one hidden and one %% not connected node, and with monitors and links between nodes. diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl index 41726b1521..0db2c1ea77 100644 --- a/lib/observer/test/observer_SUITE.erl +++ b/lib/observer/test/observer_SUITE.erl @@ -115,6 +115,7 @@ basic(doc) -> [""]; basic(Config) when is_list(Config) -> timer:send_after(100, "foobar"), %% Otherwise the timer server gets added to procs ProcsBefore = processes(), + ProcInfoBefore = [{P,process_info(P)} || P <- ProcsBefore], NumProcsBefore = length(ProcsBefore), ok = observer:start(), @@ -145,8 +146,10 @@ basic(Config) when is_list(Config) -> ProcsAfter = processes(), NumProcsAfter = length(ProcsAfter), if NumProcsAfter=/=NumProcsBefore -> + BeforeNotAfter = ProcsBefore -- ProcsAfter, ct:log("Before but not after:~n~p~n", - [[{P,process_info(P)} || P <- ProcsBefore -- ProcsAfter]]), + [[{P,I} || {P,I} <- ProcInfoBefore, + lists:member(P,BeforeNotAfter)]]), ct:log("After but not before:~n~p~n", [[{P,process_info(P)} || P <- ProcsAfter -- ProcsBefore]]), ct:fail("leaking processes"); @@ -304,10 +307,10 @@ table_win(Config) when is_list(Config) -> %% Test PR-1296/OTP-14151 %% Clicking a link to a port before the port tab has been activated the %% first time crashes observer. -port_win_when_tab_not_initiated(Config) -> +port_win_when_tab_not_initiated(_Config) -> {ok,Port} = gen_tcp:listen(0,[]), ok = observer:start(), - Notebook = setup_whitebox_testing(), + _Notebook = setup_whitebox_testing(), observer ! {open_link,erlang:port_to_list(Port)}, timer:sleep(1000), observer:stop(), diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl index 6d7e574856..ed62efbb58 100644 --- a/lib/observer/test/ttb_SUITE.erl +++ b/lib/observer/test/ttb_SUITE.erl @@ -778,37 +778,37 @@ otp_4967_2(suite) -> otp_4967_2(doc) -> ["OTP-4967: Trace message sent to {Name, Node}"]; otp_4967_2(Config) when is_list(Config) -> - io:format("1: ~p",[now()]), + io:format("1: ~p",[erlang:timestamp()]), ?line Privdir = priv_dir(Config), - io:format("2: ~p",[now()]), + io:format("2: ~p",[erlang:timestamp()]), ?line File = filename:join(Privdir,"otp_4967"), - io:format("3: ~p",[now()]), + io:format("3: ~p",[erlang:timestamp()]), ?line S = self(), - io:format("4: ~p",[now()]), + io:format("4: ~p",[erlang:timestamp()]), ?line {ok,[Node]} = ttb:tracer(node(),[{file, File}, {handler,{fun myhandler/4, S}}]), - io:format("5: ~p",[now()]), + io:format("5: ~p",[erlang:timestamp()]), %% Test that delayed registration of a process works. receive after 200 -> ok end, ?line register(otp_4967,self()), - io:format("6: ~p",[now()]), + io:format("6: ~p",[erlang:timestamp()]), ?line {ok,[{S,[{matched,Node,1}]}]} = ttb:p(self(),s), - io:format("7: ~p",[now()]), + io:format("7: ~p",[erlang:timestamp()]), ?line {otp_4967,node()} ! heihopp, - io:format("8: ~p",[now()]), + io:format("8: ~p",[erlang:timestamp()]), ?line stopped = ttb:stop([format]), - io:format("9: ~p",[now()]), + io:format("9: ~p",[erlang:timestamp()]), ?line Msgs = flush(), - io:format("10: ~p",[now()]), + io:format("10: ~p",[erlang:timestamp()]), ?line io:format("Messages received: \n~p\n",[Msgs]), - io:format("11: ~p",[now()]), + io:format("11: ~p",[erlang:timestamp()]), ?line true = lists:member(heihopp,Msgs), % the heihopp message itself - io:format("13: ~p",[now()]), + io:format("13: ~p",[erlang:timestamp()]), ?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} = lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message - io:format("14: ~p",[now()]), + io:format("14: ~p",[erlang:timestamp()]), ?line end_of_trace = lists:last(Msgs), % end of the trace ok. diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 942203bd12..fcf37a7a4d 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -119,6 +119,10 @@ <tag><c>ec_private_key() =</c></tag> <item><p><c>#'ECPrivateKey'{}</c></p></item> + <tag><c>key_params() =</c></tag> + <item><p> #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} + | {rsa, Size::integer(), PubExp::integer()} </p></item> + <tag><c>public_crypt_options() =</c></tag> <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item> @@ -347,8 +351,7 @@ <name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name> <fsummary>Generates a new keypair.</fsummary> <type> - <v>Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} - | {rsa, Size::integer(), PubExp::integer} </v> + <v>Params = key_params()</v> </type> <desc> <p>Generates a new keypair. Note that except for Diffie-Hellman @@ -769,6 +772,85 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, </desc> </func> + <func> + <name>pkix_test_data(Options) -> Config </name> + <fsummary>Creates certificate test data.</fsummary> + <type> + <v>Options = #{chain_type() := chain_opts()} </v> + <d>Options for ROOT, Intermediate and Peer certs</d> + + <v>chain_type() = server_chain | client_chain </v> + + <v>chain_opts() = #{chain_end() := [cert_opt()], + intermediates => [[cert_opt()]]}</v> + <d>A valid chain must have at least a ROOT and a peer cert</d> + + <v>chain_end() = root | peer </v> + + <v>cert_opt() = {Key, Value}</v> + <d>For available options see <seealso marker="#cert_opt"> cert_opt()</seealso> below.</d> + + <v>Config = #{server_config := [conf_opt()], + client_config := [conf_opt()]}</v> + + <v>conf_opt() = {cert, der_encoded()} | {key, der_encoded()} |{cacerts, [der_encoded()]}</v> + <d>This is a subset of the type <seealso marker="ssl:ssl#type-ssloption"> ssl:ssl_option()</seealso> </d> + </type> + + <desc> + <p>Creates certificate test data to facilitate automated testing + of applications using X509-certificates often through + SSL/TLS. The test data can be used when you have control + over both the client and the server in a test scenario. + </p> + + <p> The <marker id="cert_opt"/> cert_opt() type consists of the following options: </p> + <taglist> + <tag> {digest, digest_type()}</tag> + <item><p>Hash algorithm to be used for + signing the certificate together with the key option. Defaults to sha that is sha1. + </p></item> + <tag> {key, key_params() | private_key()}</tag> + <item><p>Parameters to be used to call public_key:generate_key/1, to generate a key, or an existing + key. Defaults to generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a very old + cryptolib.</p></item> + <tag> {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} </tag> + <item><p>The validity period of the certificate.</p></item> + <tag> {extensions, [#'Extension'{}]}</tag> + <item><p> Extensions to include in the certificate.</p> + + <p>Default extensions included in CA certificates if not + otherwise specified are: </p> + <code>[#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [keyCertSign, cRLSign], + critical = false}, +#'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA = true}, + critical = true}] + </code> + + <p>Default extensions included in the server peer cert if not + otherwise specified are: </p> + <code>[#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [digitalSignature, keyAgreement], + critical = false}, +#'Extension'{extnID = ?'id-ce-subjectAltName', + extnValue = [{dNSName, Hostname}], + critical = false}] + </code> + <p>Hostname is the result of calling net_adm:localhost() in the Erlang node + where this funcion is called. + </p></item> + + </taglist> + + <note><p> + Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain + and they can not be used to achieve real security. This function is provided for testing purposes only. +</p></note> + </desc> + </func> + <func> <name>pkix_verify(Cert, Key) -> boolean()</name> <fsummary>Verifies PKIX x.509 certificate signature.</fsummary> diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml index d34f3ed9a3..739310c88b 100644 --- a/lib/public_key/doc/src/public_key_records.xml +++ b/lib/public_key/doc/src/public_key_records.xml @@ -171,9 +171,9 @@ #'ECPrivateKey'{ version, % integer() privateKey, % binary() - parameters, % der_encoded() - {'EcpkParameters', #'ECParameters'{}} | - {'EcpkParameters', {namedCurve, oid()}} | - {'EcpkParameters', 'NULL'} % Inherited by CA + parameters, % {ecParameters, #'ECParameters'{}} | + % {namedCurve, Oid::tuple()} | + % {implicitlyCA, 'NULL'} publicKey % bitstring() }. diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index f45f2c2e9a..13833830a7 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -32,12 +32,25 @@ is_issuer/2, issuer_id/2, distribution_points/1, is_fixed_dh_cert/1, verify_data/1, verify_fun/4, select_extension/2, match_name/3, - extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1]). + extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1, + gen_test_certs/1]). -define(NULL, 0). - + +-export_type([chain_opts/0, test_config/0]). + +-type cert_opt() :: {digest, public_key:digest_type()} | + {key, public_key:key_params() | public_key:private_key()} | + {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} | + {extensions, [#'Extension'{}]}. +-type chain_end() :: root | peer. +-type chain_opts() :: #{chain_end() := [cert_opt()], intermediates => [[cert_opt()]]}. +-type conf_opt() :: {cert, public_key:der_encoded()} | + {key, public_key:der_encoded()} | + {cacerts, [public_key:der_encoded()]}. +-type test_config() :: #{server_config := [conf_opt()], client_config := [conf_opt()]}. %%==================================================================== -%% Internal application API +%% Internal application APIu %%==================================================================== %%-------------------------------------------------------------------- @@ -417,6 +430,31 @@ match_name(Fun, Name, PermittedName, [Head | Tail]) -> false -> match_name(Fun, Name, Head, Tail) end. +%%% +-spec gen_test_certs(#{server_chain:= chain_opts(), client_chain:= chain_opts()}) -> test_config(). + +%% Generates server and and client configuration for testing +%% purposes. All certificate options have default values +gen_test_certs(#{client_chain := #{root := ClientRootConf, + intermediates := ClientCAs, + peer := ClientPeer}, + server_chain := + #{root := ServerRootConf, + intermediates := ServerCAs, + peer := ServerPeer}}) -> + SRootKey = gen_key(proplists:get_value(key, ServerRootConf, default_key_gen())), + CRootKey = gen_key(proplists:get_value(key, ClientRootConf, default_key_gen())), + ServerRoot = root_cert("server", SRootKey, ClientRootConf), + ClientRoot = root_cert("client", CRootKey, ServerRootConf), + + [{ServerDERCert, ServerDERKey} | ServerCAsKeys] = config(server, ServerRoot, + SRootKey, lists:reverse([ServerPeer | lists:reverse(ServerCAs)])), + [{ClientDERCert, ClientDERKey} | ClientCAsKeys] = config(client, ClientRoot, + CRootKey, lists:reverse([ClientPeer | lists:reverse(ClientCAs)])), + ServerDERCA = ca_config(ClientRoot, ServerCAsKeys), + ClientDERCA = ca_config(ServerRoot, ClientCAsKeys), + #{server_config => [{cert, ServerDERCert}, {key, ServerDERKey}, {cacerts, ServerDERCA}], + client_config => [{cert, ClientDERCert}, {key, ClientDERKey}, {cacerts, ClientDERCA}]}. %%-------------------------------------------------------------------- %%% Internal functions @@ -1064,3 +1102,212 @@ missing_basic_constraints(OtpCert, SelfSigned, ValidationState, VerifyFun, UserS Len - 1}, UserState} end. + + gen_key(KeyGen) -> + case is_key(KeyGen) of + true -> + KeyGen; + false -> + public_key:generate_key(KeyGen) + end. + +is_key(#'DSAPrivateKey'{}) -> + true; +is_key(#'RSAPrivateKey'{}) -> + true; +is_key(#'ECPrivateKey'{}) -> + true; +is_key(_) -> + false. + +root_cert(Role, PrivKey, Opts) -> + TBS = cert_template(), + Issuer = issuer("root", Role, " ROOT CA"), + OTPTBS = TBS#'OTPTBSCertificate'{ + signature = sign_algorithm(PrivKey, Opts), + issuer = Issuer, + validity = validity(Opts), + subject = Issuer, + subjectPublicKeyInfo = public_key(PrivKey), + extensions = extensions(Role, ca, Opts) + }, + public_key:pkix_sign(OTPTBS, PrivKey). + +cert_template() -> + #'OTPTBSCertificate'{ + version = v3, + serialNumber = trunc(rand:uniform()*100000000)*10000 + 1, + issuerUniqueID = asn1_NOVALUE, + subjectUniqueID = asn1_NOVALUE + }. +issuer(Contact, Role, Name) -> + subject(Contact, Role ++ Name). + +subject(Contact, Name) -> + Opts = [{email, Contact ++ "@erlang.org"}, + {name, Name}, + {city, "Stockholm"}, + {country, "SE"}, + {org, "erlang"}, + {org_unit, "automated testing"}], + subject(Opts). + +subject(SubjectOpts) when is_list(SubjectOpts) -> + Encode = fun(Opt) -> + {Type,Value} = subject_enc(Opt), + [#'AttributeTypeAndValue'{type=Type, value=Value}] + end, + {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. + +subject_enc({name, Name}) -> + {?'id-at-commonName', {printableString, Name}}; +subject_enc({email, Email}) -> + {?'id-emailAddress', Email}; +subject_enc({city, City}) -> + {?'id-at-localityName', {printableString, City}}; +subject_enc({org, Org}) -> + {?'id-at-organizationName', {printableString, Org}}; +subject_enc({org_unit, OrgUnit}) -> + {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; +subject_enc({country, Country}) -> + {?'id-at-countryName', Country}. + +validity(Opts) -> + DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), + DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), + {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), + Format = fun({Y,M,D}) -> + lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) + end, + #'Validity'{notBefore={generalTime, Format(DefFrom)}, + notAfter ={generalTime, Format(DefTo)}}. + +sign_algorithm(#'RSAPrivateKey'{}, Opts) -> + Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)), + #'SignatureAlgorithm'{algorithm = Type, + parameters = 'NULL'}; +sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> + #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1', + parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}}; +sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) -> + Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)), + #'SignatureAlgorithm'{algorithm = Type, + parameters = Parms}. +rsa_digest_oid(sha1) -> + ?'sha1WithRSAEncryption'; +rsa_digest_oid(sha512) -> + ?'sha512WithRSAEncryption'; +rsa_digest_oid(sha384) -> + ?'sha384WithRSAEncryption'; +rsa_digest_oid(sha256) -> + ?'sha256WithRSAEncryption'; +rsa_digest_oid(md5) -> + ?'md5WithRSAEncryption'. + +ecdsa_digest_oid(sha1) -> + ?'ecdsa-with-SHA1'; +ecdsa_digest_oid(sha512) -> + ?'ecdsa-with-SHA512'; +ecdsa_digest_oid(sha384) -> + ?'ecdsa-with-SHA384'; +ecdsa_digest_oid(sha256) -> + ?'ecdsa-with-SHA256'. + +config(Role, Root, Key, Opts) -> + cert_chain(Role, Root, Key, Opts). + +cert_chain(Role, Root, RootKey, Opts) -> + cert_chain(Role, Root, RootKey, Opts, 0, []). + +cert_chain(Role, IssuerCert, IssuerKey, [PeerOpts], _, Acc) -> + Key = gen_key(proplists:get_value(key, PeerOpts, default_key_gen())), + Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), + IssuerKey, Key, "admin", " Peer cert", PeerOpts, peer), + [{Cert, Key}, {IssuerCert, IssuerKey} | Acc]; +cert_chain(Role, IssuerCert, IssuerKey, [CAOpts | Rest], N, Acc) -> + Key = gen_key(proplists:get_value(key, CAOpts, default_key_gen())), + Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin", + " Intermidiate CA " ++ integer_to_list(N), CAOpts, ca), + cert_chain(Role, Cert, Key, Rest, N+1, [{IssuerCert, IssuerKey} | Acc]). + +cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer}}, + PrivKey, Key, Contact, Name, Opts, Type) -> + TBS = cert_template(), + OTPTBS = TBS#'OTPTBSCertificate'{ + signature = sign_algorithm(PrivKey, Opts), + issuer = Issuer, + validity = validity(Opts), + subject = subject(Contact, atom_to_list(Role) ++ Name), + subjectPublicKeyInfo = public_key(Key), + extensions = extensions(Role, Type, Opts) + + }, + public_key:pkix_sign(OTPTBS, PrivKey). + +ca_config(Root, CAsKeys) -> + [Root | [CA || {CA, _} <- CAsKeys]]. + +default_key_gen() -> + case crypto:ec_curves() of + [] -> + {rsa, 2048, 17}; + [Curve |_] -> + Oid = pubkey_cert_records:namedCurves(Curve), + {namedCurve, Oid} + end. + +public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> + Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, + Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, + subjectPublicKey = Public}; +public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> + Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', + parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}; +public_key(#'ECPrivateKey'{version = _Version, + privateKey = _PrivKey, + parameters = Params, + publicKey = PubKey}) -> + Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, + subjectPublicKey = #'ECPoint'{point = PubKey}}. + +extensions(Role, Type, Opts) -> + Exts = proplists:get_value(extensions, Opts, []), + add_default_extensions(Role, Type, Exts). + +add_default_extensions(_, ca, Exts) -> + Default = [#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [keyCertSign, cRLSign], + critical = false}, + #'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA = true}, + critical = true}], + add_default_extensions(Default, Exts); + +add_default_extensions(server, peer, Exts) -> + Hostname = net_adm:localhost(), + Default = [#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [digitalSignature, keyAgreement], + critical = false}, + #'Extension'{extnID = ?'id-ce-subjectAltName', + extnValue = [{dNSName, Hostname}], + critical = false} + ], + add_default_extensions(Default, Exts); + +add_default_extensions(_, peer, Exts) -> + Exts. + +add_default_extensions(Defaults0, Exts) -> + Defaults = lists:filtermap(fun(#'Extension'{extnID = ID} = Ext) -> + case lists:keymember(ID, 2, Exts) of + true -> + false; + false -> + {true, Ext} + end + end, Defaults0), + Exts ++ Defaults. + diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index c2060c144c..cc01b61433 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -58,11 +58,13 @@ pkix_match_dist_point/2, pkix_crl_verify/2, pkix_crl_issuer/1, - short_name_hash/1 + short_name_hash/1, + pkix_test_data/1 ]). -export_type([public_key/0, private_key/0, pem_entry/0, - pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0]). + pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0, + key_params/0, digest_type/0]). -type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key(). -type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key(). @@ -71,8 +73,12 @@ -type rsa_private_key() :: #'RSAPrivateKey'{}. -type dsa_private_key() :: #'DSAPrivateKey'{}. -type dsa_public_key() :: {integer(), #'Dss-Parms'{}}. --type ec_public_key() :: {#'ECPoint'{},{namedCurve, Oid::tuple()} | #'ECParameters'{}}. +-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}. +-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}. +-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}. -type ec_private_key() :: #'ECPrivateKey'{}. +-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} | + {rsa, Size::integer(), PubExp::integer()}. -type der_encoded() :: binary(). -type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey' | 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' @@ -100,6 +106,7 @@ -type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise. -type oid() :: tuple(). +-type chain_type() :: server_chain | client_chain. -define(UINT32(X), X:32/unsigned-big-integer). -define(DER_NULL, <<5, 0>>). @@ -399,9 +406,7 @@ dh_gex_group(Min, N, Max, Groups) -> %%-------------------------------------------------------------------- -spec generate_key(#'DHParameter'{}) -> {Public::binary(), Private::binary()}; - ({namedCurve, Name ::oid()}) -> - #'ECPrivateKey'{}; - (#'ECParameters'{}) -> + (ecpk_parameters_api()) -> #'ECPrivateKey'{}; ({rsa, Size::pos_integer(), PubExp::pos_integer()}) -> #'RSAPrivateKey'{}. @@ -412,6 +417,8 @@ generate_key(#'DHParameter'{prime = P, base = G}) -> crypto:generate_key(dh, [P, G]); generate_key({namedCurve, _} = Params) -> ec_generate_key(Params); +generate_key({ecParameters, _} = Params) -> + ec_generate_key(Params); generate_key(#'ECParameters'{} = Params) -> ec_generate_key(Params); generate_key({rsa, ModulusSize, PublicExponent}) -> @@ -1025,6 +1032,22 @@ short_name_hash({rdnSequence, _Attributes} = Name) -> <<HashValue:32/little, _/binary>> = crypto:hash(sha, HashThis), string:to_lower(string:right(integer_to_list(HashValue, 16), 8, $0)). + +%%-------------------------------------------------------------------- +-spec pkix_test_data(#{chain_type() := pubkey_cert:chain_opts()}) -> + pubkey_cert:test_config(). + +%% Description: Generates OpenSSL-style hash of a name. +%%-------------------------------------------------------------------- + +pkix_test_data(#{client_chain := ClientChain0, + server_chain := ServerChain0}) -> + Default = #{intermediates => []}, + ClientChain = maps:merge(Default, ClientChain0), + ServerChain = maps:merge(Default, ServerChain0), + pubkey_cert:gen_test_certs(#{client_chain => ClientChain, + server_chain => ServerChain}). + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -1286,22 +1309,34 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E, is_integer(D) -> [E, N, D]. +-spec ec_generate_key(ecpk_parameters_api()) -> #'ECPrivateKey'{}. ec_generate_key(Params) -> Curve = ec_curve_spec(Params), Term = crypto:generate_key(ecdh, Curve), - ec_key(Term, Params). + NormParams = ec_normalize_params(Params), + ec_key(Term, NormParams). +-spec ec_normalize_params(ecpk_parameters_api()) -> ecpk_parameters(). +ec_normalize_params({namedCurve, Name}) when is_atom(Name) -> + {namedCurve, pubkey_cert_records:namedCurves(Name)}; +ec_normalize_params(#'ECParameters'{} = ECParams) -> + {ecParameters, ECParams}; +ec_normalize_params(Other) -> Other. + +-spec ec_curve_spec(ecpk_parameters_api()) -> term(). ec_curve_spec( #'ECParameters'{fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) -> Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'FieldID'.fieldType), FieldId#'FieldID'.parameters}, Curve = {PCurve#'Curve'.a, PCurve#'Curve'.b, none}, {Field, Curve, Base, Order, CoFactor}; +ec_curve_spec({ecParameters, ECParams}) -> + ec_curve_spec(ECParams); ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) -> ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)}); ec_curve_spec({namedCurve, Name}) when is_atom(Name) -> crypto:ec_curve(Name). - +-spec ec_key({PubKey::term(), PrivateKey::term()}, Params::ecpk_parameters()) -> #'ECPrivateKey'{}. ec_key({PubKey, PrivateKey}, Params) -> #'ECPrivateKey'{version = 1, privateKey = PrivateKey, diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index 80895ce97c..374fb20375 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -48,6 +48,8 @@ all() -> pkix_verify_hostname_cn, pkix_verify_hostname_subjAltName, pkix_verify_hostname_options, + pkix_test_data_all_default, + pkix_test_data, short_cert_issuer_hash, short_crl_issuer_hash, ssh_hostkey_fingerprint_md5_implicit, ssh_hostkey_fingerprint_md5, @@ -60,7 +62,8 @@ all() -> groups() -> [{pem_decode_encode, [], [dsa_pem, rsa_pem, ec_pem, encrypted_pem, - dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]}, + dh_pem, cert_pem, pkcs7_pem, pkcs10_pem, ec_pem2, + ec_pem_encode_generated]}, {ssh_public_key_decode_encode, [], [ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key, ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment, @@ -92,6 +95,14 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. %%------------------------------------------------------------------- + +init_per_testcase(pkix_test_data_all_default, Config) -> + case crypto:ec_curves() of + [] -> + {skip, missing_ecc_support}; + _ -> + init_common_per_testcase(Config) + end; init_per_testcase(TestCase, Config) -> case TestCase of ssh_hostkey_fingerprint_md5_implicit -> init_fingerprint_testcase([md5], Config); @@ -101,6 +112,7 @@ init_per_testcase(TestCase, Config) -> ssh_hostkey_fingerprint_sha384 -> init_fingerprint_testcase([sha384], Config); ssh_hostkey_fingerprint_sha512 -> init_fingerprint_testcase([sha512], Config); ssh_hostkey_fingerprint_list -> init_fingerprint_testcase([sha,md5], Config); + ec_pem_encode_generated -> init_ec_pem_encode_generated(Config); _ -> init_common_per_testcase(Config) end. @@ -217,9 +229,47 @@ ec_pem(Config) when is_list(Config) -> true = check_entry_type(ECParams, 'EcpkParameters'), ECPrivKey = public_key:pem_entry_decode(Entry2), true = check_entry_type(ECPrivKey, 'ECPrivateKey'), + true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'), ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem), ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])). +ec_pem2() -> + [{doc, "EC key w/explicit params PEM-file decode/encode"}]. +ec_pem2(Config) when is_list(Config) -> + Datadir = proplists:get_value(data_dir, Config), + + %% Load key with explicit curve parameters. Generated with... + %% openssl ecparam -name secp521r1 -genkey -param_enc explicit -out ec_key2.pem + {ok, ECPrivPem} = file:read_file(filename:join(Datadir, "ec_key2.pem")), + [{'EcpkParameters', _, not_encrypted} = Entry1, + {'ECPrivateKey', _, not_encrypted} = Entry2] = public_key:pem_decode(ECPrivPem), + + ECParams = public_key:pem_entry_decode(Entry1), + true = check_entry_type(ECParams, 'EcpkParameters'), + ECPrivKey = public_key:pem_entry_decode(Entry2), + true = check_entry_type(ECPrivKey, 'ECPrivateKey'), + true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'), + ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem), + ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])). + + +init_ec_pem_encode_generated(Config) -> + case catch true = lists:member('secp384r1', crypto:ec_curves()) of + {'EXIT', _} -> {skip, {'secp384r1', not_supported}}; + _ -> init_common_per_testcase(Config) + end. + +ec_pem_encode_generated() -> + [{doc, "PEM-encode generated EC key"}]. +ec_pem_encode_generated(Config) -> + + Key1 = public_key:generate_key({namedCurve, 'secp384r1'}), + public_key:pem_entry_encode('ECPrivateKey', Key1), + + Key2 = public_key:generate_key({namedCurve, ?'secp384r1'}), + public_key:pem_entry_encode('ECPrivateKey', Key2). + + %%-------------------------------------------------------------------- encrypted_pem() -> @@ -1007,6 +1057,84 @@ general_name(Config) when is_list(Config) -> authorityCertSerialNumber = 1}). %%-------------------------------------------------------------------- + +pkix_test_data_all_default() -> + [{doc, "Test API function pkix_test_data/1"}]. + +pkix_test_data_all_default(Config) when is_list(Config) -> + #{server_config := ServerConf0, + client_config := ClientConf0} = public_key:pkix_test_data(#{server_chain => + #{root => [], + intermediates => [[]], + peer => []}, + client_chain => + #{root => [], + intermediates => [[]], + peer => []}}), + check_conf_member(ServerConf0, [key, cert, cacerts]), + check_conf_member(ClientConf0, [key, cert, cacerts]), + + 3 = length(proplists:get_value(cacerts, ServerConf0)), + 3 = length(proplists:get_value(cacerts, ServerConf0)), + + #{server_config := ServerConf1, + client_config := ClientConf1} = public_key:pkix_test_data(#{server_chain => + #{root => [], + peer => []}, + client_chain => + #{root => [], + peer => []}}), + 2 = length(proplists:get_value(cacerts, ServerConf1)), + 2 = length(proplists:get_value(cacerts, ServerConf1)), + + check_conf_member(ServerConf1, [key, cert, cacerts]), + check_conf_member(ClientConf1, [key, cert, cacerts]). + + +pkix_test_data() -> + [{doc, "Test API function pkix_test_data/1"}]. + +pkix_test_data(Config) when is_list(Config) -> + {Year, Month, Day} = date(), + Keygen = + case crypto:ec_curves() of + [] -> + {rsa, 2048, 17}; + [Curve |_] -> + Oid = pubkey_cert_records:namedCurves(Curve), + {namedCurve, Oid} + end, + #{server_config := ServerConf0, + client_config := ClientConf0} = + public_key:pkix_test_data(#{server_chain => + #{root => [], + intermediates => [], + peer => [{key, hardcode_rsa_key()}]}, + client_chain => + #{root => [{validity, {{Year-2, Month, Day}, + {Year-1, Month, Day}}}], + intermediates => + [[{extensions, [#'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA=true, + pathLenConstraint = 1}, + critical = true}]}]], + peer => [{key, Keygen}, {digest, sha1}]}}), + check_conf_member(ServerConf0, [key, cert, cacerts]), + check_conf_member(ClientConf0, [key, cert, cacerts]). + + + +check_conf_member(_, []) -> + true; +check_conf_member(Conf, [Member | Rest]) -> + case lists:keymember(Member, 1, Conf) of + true -> + check_conf_member(Conf, Rest); + false -> + ct:fail({misssing_conf, Member}) + end. + +%%-------------------------------------------------------------------- short_cert_issuer_hash() -> [{doc, "Test OpenSSL-style hash for certificate issuer"}]. @@ -1095,7 +1223,7 @@ check_entry_type(#'ECPrivateKey'{}, 'ECPrivateKey') -> true; check_entry_type({namedCurve, _}, 'EcpkParameters') -> true; -check_entry_type(#'ECParameters'{}, 'EcpkParameters') -> +check_entry_type({ecParameters, #'ECParameters'{}}, 'EcpkParameters') -> true; check_entry_type(_,_) -> false. @@ -1128,3 +1256,15 @@ ssh_hostkey(rsa) -> public_key), PKdecoded. +hardcode_rsa_key() -> + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, + publicExponent = 17, + privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, + prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, + prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, + exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, + exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, + coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, + otherPrimeInfos = asn1_NOVALUE}. diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key2.pem b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem new file mode 100644 index 0000000000..56b8169e86 --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem @@ -0,0 +1,29 @@ +-----BEGIN EC PARAMETERS----- +MIIBwgIBATBNBgcqhkjOPQEBAkIB//////////////////////////////////// +//////////////////////////////////////////////////8wgZ4EQgH///// +//////////////////////////////////////////////////////////////// +/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh +Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5 +MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte +d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY +9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC +QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3 +CaXQO7XJuImcR667b7cekThkCQIBAQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIICnQIBAQRCAVE6lUKRj5AE8Cw21A+iPWhXSg+XNuerrTyeFERY6AtOrRJ9mTQ3 +Av3xjiM3zhZy2KWnm62hvkvlGbZ7iDKcqg2GoIIBxjCCAcICAQEwTQYHKoZIzj0B +AQJCAf////////////////////////////////////////////////////////// +////////////////////////////MIGeBEIB//////////////////////////// +//////////////////////////////////////////////////////////wEQVGV +PrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ4VYZOVHsfpN7FlLAvTuxvwc1 +c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcXOTKEqqDaZLoEgYUEAMaFjga3 +BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPB +hWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZmPVESVebRGgXr70XJz5mLJfu +cple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQAkIB//////////////////// +///////////////////////6UYaHg78vlmt/zAFI9wml0Du1ybiJnEeuu2+3HpE4 +ZAkCAQGhgYkDgYYABAFLBJzBphlIJmSPuXzTDTnZpL7A0fnyqit9V3TBvaOcL6Iw +6m2TpXvNakxi8Flj0Ok4hdRt+YhawFs0bmzZCT8kfAFs7p55BPHk7FaMZaba77R8 +4V6MhUJSKLc0I/XQBtvoOgVlPJ0MPOndnIxPspCPll886yxG5kOMUAx3HjFg16RT +eA== +-----END EC PRIVATE KEY----- diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 83a77d2a28..bb96c2237d 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.4.1 +PUBLIC_KEY_VSN = 1.5 diff --git a/lib/reltool/src/reltool.app.src b/lib/reltool/src/reltool.app.src index 90f93d2901..dc21c1cfce 100644 --- a/lib/reltool/src/reltool.app.src +++ b/lib/reltool/src/reltool.app.src @@ -36,6 +36,6 @@ {registered, []}, {applications, [stdlib, kernel]}, {env, []}, - {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-2.0","sasl-2.4", + {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-3.4","sasl-2.4", "kernel-3.0","erts-7.0"]} ]}. diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src index d75543a91b..1e8e58a978 100644 --- a/lib/sasl/src/sasl.app.src +++ b/lib/sasl/src/sasl.app.src @@ -43,6 +43,6 @@ {env, [{sasl_error_logger, tty}, {errlog_type, all}]}, {mod, {sasl, []}}, - {runtime_dependencies, ["tools-2.6.14","stdlib-3.0","kernel-5.0", - "erts-8.1"]}]}. + {runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-5.3", + "erts-9.0"]}]}. diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index 064dcd6892..51407ef3b9 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -63,7 +63,7 @@ {applications, [crypto, public_key, kernel, stdlib]}, {env, []}, {mod, {ssl_app, []}}, - {runtime_dependencies, ["stdlib-3.2","public_key-1.2","kernel-3.0", + {runtime_dependencies, ["stdlib-3.2","public_key-1.5","kernel-3.0", "erts-7.0","crypto-3.3", "inets-5.10.7"]}]}. diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 64e8042b25..f38c0a7416 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -232,103 +232,150 @@ end_per_testcase(_TestCase, Config) -> %% ECDH_RSA client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], ecdh_rsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). %% ECDHE_RSA client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_ecdsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_ecdsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). - + %% ECDH_ECDSA client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], ecdh_ecdsa, ecdh_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], - ecdhe_rsa, ecdh_ecdsa, Config), - basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], + ecdhe_rsa, ecdh_ecdsa, Config), + basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], - ecdhe_ecdsa, ecdh_ecdsa, Config), + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], + ecdhe_ecdsa, ecdh_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). %% ECDHE_ECDSA client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_ecdsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}] + , ecdhe_ecdsa, ecdhe_ecdsa, Config), ServerKeyFile = proplists:get_value(keyfile, SOpts), {ok, PemBin} = file:read_file(ServerKeyFile), PemEntries = public_key:pem_decode(PemBin), - {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), + {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), ServerKey = {'ECPrivateKey', Key}, SType = proplists:get_value(server_type, Config), CType = proplists:get_value(client_type, Config), {Server, Port} = start_server_with_raw_key(SType, [{key, ServerKey} | proplists:delete(keyfile, SOpts)], - Config), + Config), Client = start_client(CType, Port, COpts, Config), - check_result(Server, SType, Client, CType), + check_result(Server, SType, Client, CType), close(Server, Client). ecc_default_order(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [], case supported_eccs([{eccs, [sect571r1]}]) of true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} - end. + end. ecc_default_order_custom_curves(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of - true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. ecc_client_order(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, false}], case supported_eccs([{eccs, [sect571r1]}]) of - true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. ecc_client_order_custom_curves(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); @@ -336,45 +383,62 @@ ecc_client_order_custom_curves(Config) -> end. ecc_unknown_curve(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, ['123_fake_curve']}], ecc_test_error(COpts, SOpts, [], ECCOpts, Config). client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], - case supported_eccs(ECCOpts) of - true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); - false -> {skip, "unsupported named curves"} - end. + case supported_eccs(ECCOpts) of + true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); + false -> {skip, "unsupported named curves"} + end. client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_rsa, Config), - ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_rsa, Config), + ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of - true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} - end. + end. client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], ecdhe_rsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]}, + {client_chain, Default}], + ecdhe_rsa, ecdh_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); @@ -382,7 +446,10 @@ client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); @@ -390,7 +457,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); @@ -398,7 +468,10 @@ client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config); @@ -406,7 +479,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) -> end. client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config); diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index c3fd73bf09..0bc265fa10 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -439,7 +439,7 @@ server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) -> [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs), PartialChain = fun(_CertChain) -> - ture = false %% crash on purpose + ture = false %% crash on purpose end, Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, @@ -567,9 +567,12 @@ cert_expired() -> cert_expired(Config) when is_list(Config) -> {Year, Month, Day} = date(), Active = proplists:get_value(active, Config), - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_ca_0, - [{validity, {{Year-2, Month, Day}, - {Year-1, Month, Day}}}]}], + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[], + [{validity, {{Year-2, Month, Day}, + {Year-1, Month, Day}}}], + [] + ]}], Config, "_expired"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), @@ -598,11 +601,11 @@ extended_key_usage_verify_server() -> [{doc,"Test cert that has a critical extended_key_usage extension in server cert"}]. extended_key_usage_verify_server(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, - [{?'id-ce-extKeyUsage', - [?'id-kp-serverAuth'], true}] - }]}], Config, "_keyusage_server"), + Ext = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-serverAuth'], true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[], [{extensions, Ext}]]}], Config, + "_keyusage_server"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -632,14 +635,13 @@ extended_key_usage_verify_both() -> [{doc,"Test cert that has a critical extended_key_usage extension in client verify_peer mode"}]. extended_key_usage_verify_both(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{?'id-ce-extKeyUsage', - [?'id-kp-serverAuth'], true}] - }]}, - {client_peer_opts, - [{extensions, [{?'id-ce-extKeyUsage', - [?'id-kp-clientAuth'], true}] - }]}], Config, "_keyusage_both"), + ServerExt = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-serverAuth'], true}]), + ClientExt = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-clientAuth'], true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, [[],[],[{extensions, ClientExt}]]}, + {server_chain, [[],[],[{extensions, ServerExt}]]}], + Config, "_keyusage_both"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -668,10 +670,10 @@ critical_extension_verify_server() -> [{doc,"Test cert that has a critical unknown extension in verify_peer mode"}]. critical_extension_verify_server(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_client_unknown_extension"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[],[], [{extensions, Ext}]]}], + Config, "_client_unknown_extension"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -705,10 +707,10 @@ critical_extension_verify_client() -> [{doc,"Test cert that has a critical unknown extension in verify_peer mode"}]. critical_extension_verify_client(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_server_unknown_extensions"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[],[{extensions, Ext}]]}], + Config, "_server_unknown_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -741,11 +743,10 @@ critical_extension_verify_none() -> [{doc,"Test cert that has a critical unknown extension in verify_none mode"}]. critical_extension_verify_none(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, - [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_unknown_extensions"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[], [{extensions, Ext}]]}], + Config, "_unknown_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -780,12 +781,7 @@ no_authority_key_identifier() -> " but are present in trusted certs db."}]. no_authority_key_identifier(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}, - {client_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}], Config, "_peer_no_auth_key_id"), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([], Config, "_peer_no_auth_key_id"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), @@ -822,14 +818,10 @@ no_authority_key_identifier_keyEncipherment() -> " authorityKeyIdentifier extension, but are present in trusted certs db."}]. no_authority_key_identifier_keyEncipherment(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{auth_key_id, undefined}, - {key_usage, [digitalSignature, - keyEncipherment]}] - }]}, - {client_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}], Config, "_peer_keyEncipherment"), + ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[],[],[{extensions, ClientExt}]]}], + Config, "_peer_keyEncipherment"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -932,12 +924,10 @@ client_with_cert_cipher_suites_handshake() -> [{doc, "Test that client with a certificate without keyEncipherment usage " " extension can connect to a server with restricted cipher suites "}]. client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, - [{key_usage, [digitalSignature]}] - }]}], Config, "_sign_only_extensions"), - - + Ext = x509_test:extensions([{key_usage, [digitalSignature]}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[], [], [{extensions, Ext}]]}], + Config, "_sign_only_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index a5f03a1f15..4e7252f469 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -449,11 +449,12 @@ make_dsa_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of true -> + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]), - KeyGenSpec = key_gen_info(dsa, dsa), - - GenCertData = x509_test:gen_test_certs([{digest, sha} | KeyGenSpec]), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -469,12 +470,13 @@ make_dsa_cert(Config) -> false -> Config end. -make_rsa_cert_chains(ChainConf, Config, Suffix) -> - CryptoSupport = crypto:supports(), - KeyGenSpec = key_gen_info(rsa, rsa), +make_rsa_cert_chains(UserConf, Config, Suffix) -> + ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()), + CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]), - GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -482,12 +484,13 @@ make_rsa_cert_chains(ChainConf, Config, Suffix) -> [{reuseaddr, true}, {verify, verify_peer} | ServerConf] }. -make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) -> - CryptoSupport = crypto:supports(), - KeyGenSpec = key_gen_info(ClientChainType, ServerChainType), +make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) -> + ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()), + CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]), - GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -495,56 +498,113 @@ make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) -> [{reuseaddr, true}, {verify, verify_peer} | ServerConf] }. -key_gen_info(ClientChainType, ServerChainType) -> - key_gen_spec("client", ClientChainType) ++ key_gen_spec("server", ServerChainType). +default_cert_chain_conf() -> + %% Use only default options + [[],[],[]]. + +gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) -> + ClientTag = conf_tag("client"), + ServerTag = conf_tag("server"), + + DefaultClient = chain_spec(client, ClientChainType), + DefaultServer = chain_spec(server, ServerChainType), + + ClientConf = merge_chain_spec(UserClient, DefaultClient, []), + ServerConf = merge_chain_spec(UserServer, DefaultServer, []), + + new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]). + +new_format(Conf) -> + CConf = proplists:get_value(client_chain, Conf), + SConf = proplists:get_value(server_chain, Conf), + #{server_chain => proplist_to_map(SConf), + client_chain => proplist_to_map(CConf)}. + +proplist_to_map([Head | Rest]) -> + [Last | Tail] = lists:reverse(Rest), + #{root => Head, + intermediates => lists:reverse(Tail), + peer => Last}. + +conf_tag(Role) -> + list_to_atom(Role ++ "_chain"). -key_gen_spec(Role, ecdh_rsa) -> +chain_spec(_Role, ecdh_rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(1), - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdhe_ecdsa) -> + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, {namedCurve, CurveOid}}]]; + +chain_spec(_Role, ecdhe_ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdh_ecdsa) -> + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; + +chain_spec(_Role, ecdh_ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdhe_rsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2), - hardcode_rsa_key(3)]} - ]; -key_gen_spec(Role, rsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2), - hardcode_rsa_key(3)]} - ]; -key_gen_spec(Role, dsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_dsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_dsa_key(2), - hardcode_dsa_key(3)]} - ]. + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; +chain_spec(_Role, ecdhe_rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, hardcode_rsa_key(2)}], + [Digest, {key, hardcode_rsa_key(3)}]]; +chain_spec(_Role, ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + CurveOid = hd(tls_v1:ecc_curves(0)), + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; +chain_spec(_Role, rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, hardcode_rsa_key(2)}], + [Digest, {key, hardcode_rsa_key(3)}]]; +chain_spec(_Role, dsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_dsa_key(1)}], + [Digest, {key, hardcode_dsa_key(2)}], + [Digest, {key, hardcode_dsa_key(3)}]]. + +merge_chain_spec([], [], Acc)-> + lists:reverse(Acc); +merge_chain_spec([User| UserRest], [Default | DefaultRest], Acc) -> + Merge = merge_spec(User, Default, confs(), []), + merge_chain_spec(UserRest, DefaultRest, [Merge | Acc]). + +confs() -> + [key, digest, validity, extensions]. + +merge_spec(_, _, [], Acc) -> + Acc; +merge_spec(User, Default, [Conf | Rest], Acc) -> + case proplists:get_value(Conf, User, undefined) of + undefined -> + case proplists:get_value(Conf, Default, undefined) of + undefined -> + merge_spec(User, Default, Rest, Acc); + Value -> + merge_spec(User, Default, Rest, [{Conf, Value} | Acc]) + end; + Value -> + merge_spec(User, Default, Rest, [{Conf, Value} | Acc]) + end. + make_ecdsa_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]), - CurveOid = hd(tls_v1:ecc_curves(0)), - GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}}, - {client_key_gen, {namedCurve, CurveOid}}, - {server_key_gen_chain, [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]}, - {client_key_gen_chain, [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -563,13 +623,10 @@ make_rsa_cert(Config) -> true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]), - GenCertData = x509_test:gen_test_certs([{server_key_gen, hardcode_rsa_key(1)}, - {client_key_gen, hardcode_rsa_key(2)}, - {server_key_gen_chain, [hardcode_rsa_key(3), - hardcode_rsa_key(4)]}, - {client_key_gen_chain, [hardcode_rsa_key(5), - hardcode_rsa_key(6)]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -601,16 +658,10 @@ make_ecdh_rsa_cert(Config) -> true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]), - CurveOid = hd(tls_v1:ecc_curves(0)), - GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}}, - {client_key_gen, {namedCurve, CurveOid}}, - {server_key_gen_chain, [hardcode_rsa_key(1), - {namedCurve, CurveOid} - ]}, - {client_key_gen_chain, [hardcode_rsa_key(2), - {namedCurve, CurveOid} - ]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -1509,73 +1560,79 @@ tls_version(Atom) -> tls_record:protocol_version(Atom). hardcode_rsa_key(1) -> - {'RSAPrivateKey', 'two-prime', - 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, - 17, - 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, - 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, - 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, - 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, - 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, - 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, + publicExponent = 17, + privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, + prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, + prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, + exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, + exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, + coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(2) -> -{'RSAPrivateKey', 'two-prime', - 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777, - 17, - 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773, - 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419, - 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083, - 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677, - 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029, - 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540, - asn1_NOVALUE}; - + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777, + publicExponent = 17, + privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773, + prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419, + prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083, + exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677, + exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029, + coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(3) -> -{'RSAPrivateKey', 'two-prime', - 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429, - 17, - 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265, - 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823, - 146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523, - 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349, - 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609, - 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429, + publicExponent = 17, + privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265, + prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823, + prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523, + exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349, + exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609, + coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(4) -> -{'RSAPrivateKey', 'two-prime', - 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389, - 17, - 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641, - 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867, - 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967, - 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541, - 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347, - 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version ='two-prime', + modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389, + publicExponent = 17, + privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641, + prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867, + prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967, + exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541, + exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347, + coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012, + otherPrimeInfos = asn1_NOVALUE}; + hardcode_rsa_key(5) -> -{'RSAPrivateKey', 'two-prime', - 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633, - 17, - 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001, - 163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709, - 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637, - 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441, - 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973, - 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version= 'two-prime', + modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633, + publicExponent = 17, + privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001, + prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709, + prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637, + exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441, + exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973, + coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(6) -> -{'RSAPrivateKey', 'two-prime', - 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039, - 17, - 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713, - 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063, - 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953, - 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125, - 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689, - 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227, - asn1_NOVALUE}. + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039, + publicExponent = 17, + privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713, + prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063, + prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953, + exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125, + exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689, + coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227, + otherPrimeInfos = asn1_NOVALUE}. hardcode_dsa_key(1) -> {'DSAPrivateKey',0, @@ -1585,19 +1642,21 @@ hardcode_dsa_key(1) -> 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, 1457508827177594730669011716588605181448418352823}; hardcode_dsa_key(2) -> - {'DSAPrivateKey',0, - 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151, - 742801637799670234315651916144768554943688916729, - 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505, - 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228, - 801315110178350279541885862867982846569980443911}; + #'DSAPrivateKey'{ + version = 0, + p = 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151, + q = 742801637799670234315651916144768554943688916729, + g = 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505, + y = 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228, + x = 801315110178350279541885862867982846569980443911}; hardcode_dsa_key(3) -> - {'DSAPrivateKey',0, - 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491, - 1454908511695148818053325447108751926908854531909, - 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579, - 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, - 1457508827177594730669011716588605181448418352823}. + #'DSAPrivateKey'{ + version = 0, + p = 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491, + q = 1454908511695148818053325447108751926908854531909, + g = 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579, + y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, + x = 1457508827177594730669011716588605181448418352823}. dtls_hello() -> [1, diff --git a/lib/ssl/test/x509_test.erl b/lib/ssl/test/x509_test.erl index 4da1537ef6..031fad1216 100644 --- a/lib/ssl/test/x509_test.erl +++ b/lib/ssl/test/x509_test.erl @@ -24,23 +24,10 @@ -include_lib("public_key/include/public_key.hrl"). - -export([gen_test_certs/1, gen_pem_config_files/3]). +-export([extensions/1, gen_pem_config_files/3]). - gen_test_certs(Opts) -> - SRootKey = gen_key(proplists:get_value(server_key_gen, Opts)), - CRootKey = gen_key(proplists:get_value(client_key_gen, Opts)), - ServerRoot = root_cert("server", SRootKey, Opts), - ClientRoot = root_cert("client", CRootKey, Opts), - [{ServerCert, ServerKey} | ServerCAsKeys] = config(server, ServerRoot, SRootKey, Opts), - [{ClientCert, ClientKey} | ClientCAsKeys] = config(client, ClientRoot, CRootKey, Opts), - ServerCAs = ca_config(ClientRoot, ServerCAsKeys), - ClientCAs = ca_config(ServerRoot, ClientCAsKeys), - [{server_config, [{cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCAs}]}, - {client_config, [{cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCAs}]}]. - -gen_pem_config_files(GenCertData, ClientBase, ServerBase) -> - ServerConf = proplists:get_value(server_config, GenCertData), - ClientConf = proplists:get_value(client_config, GenCertData), +gen_pem_config_files(#{server_config := ServerConf, + client_config := ClientConf}, ClientBase, ServerBase) -> ServerCaCertFile = ServerBase ++ "_server_cacerts.pem", ServerCertFile = ServerBase ++ "_server_cert.pem", @@ -62,147 +49,33 @@ gen_pem_config_files(GenCertData, ClientBase, ServerBase) -> {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]}, {client_config, [{certfile, ClientCertFile}, {keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}]. - - - do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) -> - CAs = proplists:get_value(cacerts, Config), - Cert = proplists:get_value(cert, Config), - Key = proplists:get_value(key, Config), - der_to_pem(CertFile, [cert_entry(Cert)]), - der_to_pem(KeyFile, [key_entry(Key)]), - der_to_pem(CAFile, ca_entries(CAs)). - - cert_entry(Cert) -> - {'Certificate', Cert, not_encrypted}. - - key_entry(Key = #'RSAPrivateKey'{}) -> - Der = public_key:der_encode('RSAPrivateKey', Key), - {'RSAPrivateKey', Der, not_encrypted}; - key_entry(Key = #'DSAPrivateKey'{}) -> - Der = public_key:der_encode('DSAPrivateKey', Key), - {'DSAPrivateKey', Der, not_encrypted}; - key_entry(Key = #'ECPrivateKey'{}) -> - Der = public_key:der_encode('ECPrivateKey', Key), - {'ECPrivateKey', Der, not_encrypted}. - - ca_entries(CAs) -> - [{'Certificate', CACert, not_encrypted} || CACert <- CAs]. - - gen_key(KeyGen) -> - case is_key(KeyGen) of - true -> - KeyGen; - false -> - public_key:generate_key(KeyGen) - end. - -root_cert(Role, PrivKey, Opts) -> - TBS = cert_template(), - Issuer = issuer("root", Role, " ROOT CA"), - OTPTBS = TBS#'OTPTBSCertificate'{ - signature = sign_algorithm(PrivKey, Opts), - issuer = Issuer, - validity = validity(Opts), - subject = Issuer, - subjectPublicKeyInfo = public_key(PrivKey), - extensions = extensions(Role, ca, Opts) - }, - public_key:pkix_sign(OTPTBS, PrivKey). - -config(Role, Root, Key, Opts) -> - KeyGenOpt = list_to_atom(atom_to_list(Role) ++ "_key_gen_chain"), - KeyGens = proplists:get_value(KeyGenOpt, Opts, default_key_gen()), - Keys = lists:map(fun gen_key/1, KeyGens), - cert_chain(Role, Root, Key, Opts, Keys). - -cert_template() -> - #'OTPTBSCertificate'{ - version = v3, - serialNumber = trunc(rand:uniform()*100000000)*10000 + 1, - issuerUniqueID = asn1_NOVALUE, - subjectUniqueID = asn1_NOVALUE - }. - -issuer(Contact, Role, Name) -> - subject(Contact, Role ++ Name). - -subject(Contact, Name) -> - Opts = [{email, Contact ++ "@erlang.org"}, - {name, Name}, - {city, "Stockholm"}, - {country, "SE"}, - {org, "erlang"}, - {org_unit, "automated testing"}], - subject(Opts). - -subject(SubjectOpts) when is_list(SubjectOpts) -> - Encode = fun(Opt) -> - {Type,Value} = subject_enc(Opt), - [#'AttributeTypeAndValue'{type=Type, value=Value}] - end, - {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. - -subject_enc({name, Name}) -> - {?'id-at-commonName', {printableString, Name}}; -subject_enc({email, Email}) -> - {?'id-emailAddress', Email}; -subject_enc({city, City}) -> - {?'id-at-localityName', {printableString, City}}; -subject_enc({state, State}) -> - {?'id-at-stateOrProvinceName', {printableString, State}}; -subject_enc({org, Org}) -> - {?'id-at-organizationName', {printableString, Org}}; -subject_enc({org_unit, OrgUnit}) -> - {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; -subject_enc({country, Country}) -> - {?'id-at-countryName', Country}; -subject_enc({serial, Serial}) -> - {?'id-at-serialNumber', Serial}; -subject_enc({title, Title}) -> - {?'id-at-title', {printableString, Title}}; -subject_enc({dnQualifer, DnQ}) -> - {?'id-at-dnQualifier', DnQ}; -subject_enc(Other) -> - Other. - -validity(Opts) -> - DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), - DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), - {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), - Format = fun({Y,M,D}) -> - lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) - end, - #'Validity'{notBefore={generalTime, Format(DefFrom)}, - notAfter ={generalTime, Format(DefTo)}}. - -extensions(Role, Type, Opts) -> - Exts = proplists:get_value(extensions, Opts, []), - lists:flatten([extension(Ext) || Ext <- default_extensions(Role, Type, Exts)]). - -%% Common extension: name_constraints, policy_constraints, ext_key_usage, inhibit_any, -%% auth_key_id, subject_key_id, policy_mapping, - -default_extensions(_, ca, Exts) -> - Def = [{key_usage, [keyCertSign, cRLSign]}, - {basic_constraints, default}], - add_default_extensions(Def, Exts); - -default_extensions(server, peer, Exts) -> - Hostname = net_adm:localhost(), - Def = [{key_usage, [digitalSignature, keyAgreement]}, - {subject_alt, Hostname}], - add_default_extensions(Def, Exts); - -default_extensions(_, peer, Exts) -> - Exts. - -add_default_extensions(Def, Exts) -> - Filter = fun({Key, _}, D) -> - lists:keydelete(Key, 1, D); - ({Key, _, _}, D) -> - lists:keydelete(Key, 1, D) - end, - Exts ++ lists:foldl(Filter, Def, Exts). +extensions(Exts) -> + [extension(Ext) || Ext <- Exts]. + + +do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) -> + CAs = proplists:get_value(cacerts, Config), + Cert = proplists:get_value(cert, Config), + Key = proplists:get_value(key, Config), + der_to_pem(CertFile, [cert_entry(Cert)]), + der_to_pem(KeyFile, [key_entry(Key)]), + der_to_pem(CAFile, ca_entries(CAs)). + +cert_entry(Cert) -> + {'Certificate', Cert, not_encrypted}. + +key_entry(Key = #'RSAPrivateKey'{}) -> + Der = public_key:der_encode('RSAPrivateKey', Key), + {'RSAPrivateKey', Der, not_encrypted}; +key_entry(Key = #'DSAPrivateKey'{}) -> + Der = public_key:der_encode('DSAPrivateKey', Key), + {'DSAPrivateKey', Der, not_encrypted}; +key_entry(Key = #'ECPrivateKey'{}) -> + Der = public_key:der_encode('ECPrivateKey', Key), + {'ECPrivateKey', Der, not_encrypted}. + +ca_entries(CAs) -> + [{'Certificate', CACert, not_encrypted} || CACert <- CAs]. extension({_, undefined}) -> []; @@ -222,13 +95,6 @@ extension({basic_constraints, Data}) -> #'Extension'{extnID = ?'id-ce-basicConstraints', extnValue = Data} end; -extension({auth_key_id, {Oid, Issuer, SNr}}) -> - #'Extension'{extnID = ?'id-ce-authorityKeyIdentifier', - extnValue = #'AuthorityKeyIdentifier'{ - keyIdentifier = Oid, - authorityCertIssuer = Issuer, - authorityCertSerialNumber = SNr}, - critical = false}; extension({key_usage, Value}) -> #'Extension'{extnID = ?'id-ce-keyUsage', extnValue = Value, @@ -240,113 +106,6 @@ extension({subject_alt, Hostname}) -> extension({Id, Data, Critical}) -> #'Extension'{extnID = Id, extnValue = Data, critical = Critical}. -public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> - Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, - Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, - subjectPublicKey = Public}; -public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> - Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', - parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}; -public_key(#'ECPrivateKey'{version = _Version, - privateKey = _PrivKey, - parameters = Params, - publicKey = PubKey}) -> - Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, - subjectPublicKey = #'ECPoint'{point = PubKey}}. - -sign_algorithm(#'RSAPrivateKey'{}, Opts) -> - Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)), - #'SignatureAlgorithm'{algorithm = Type, - parameters = 'NULL'}; -sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> - #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1', - parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}}; -sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) -> - Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)), - #'SignatureAlgorithm'{algorithm = Type, - parameters = Parms}. - -rsa_digest_oid(sha1) -> - ?'sha1WithRSAEncryption'; -rsa_digest_oid(sha512) -> - ?'sha512WithRSAEncryption'; -rsa_digest_oid(sha384) -> - ?'sha384WithRSAEncryption'; -rsa_digest_oid(sha256) -> - ?'sha256WithRSAEncryption'; -rsa_digest_oid(md5) -> - ?'md5WithRSAEncryption'. - -ecdsa_digest_oid(sha1) -> - ?'ecdsa-with-SHA1'; -ecdsa_digest_oid(sha512) -> - ?'ecdsa-with-SHA512'; -ecdsa_digest_oid(sha384) -> - ?'ecdsa-with-SHA384'; -ecdsa_digest_oid(sha256) -> - ?'ecdsa-with-SHA256'. - -ca_config(Root, CAsKeys) -> - [Root | [CA || {CA, _} <- CAsKeys]]. - -cert_chain(Role, Root, RootKey, Opts, Keys) -> - cert_chain(Role, Root, RootKey, Opts, Keys, 0, []). - -cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key], _, Acc) -> - PeerOpts = list_to_atom(atom_to_list(Role) ++ "_peer_opts"), - Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), - IssuerKey, Key, "admin", " Peer cert", Opts, PeerOpts, peer), - [{Cert, Key}, {IssuerCert, IssuerKey} | Acc]; -cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key | Keys], N, Acc) -> - CAOpts = list_to_atom(atom_to_list(Role) ++ "_ca_" ++ integer_to_list(N)), - Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin", - " Intermidiate CA " ++ integer_to_list(N), Opts, CAOpts, ca), - cert_chain(Role, Cert, Key, Opts, Keys, N+1, [{IssuerCert, IssuerKey} | Acc]). - -cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer, - serialNumber = SNr - }}, - PrivKey, Key, Contact, Name, Opts, CertOptsName, Type) -> - CertOpts = proplists:get_value(CertOptsName, Opts, []), - TBS = cert_template(), - OTPTBS = TBS#'OTPTBSCertificate'{ - signature = sign_algorithm(PrivKey, Opts), - issuer = Issuer, - validity = validity(CertOpts), - subject = subject(Contact, atom_to_list(Role) ++ Name), - subjectPublicKeyInfo = public_key(Key), - extensions = extensions(Role, Type, - add_default_extensions([{auth_key_id, {auth_key_oid(Role), Issuer, SNr}}], - CertOpts)) - }, - public_key:pkix_sign(OTPTBS, PrivKey). - -is_key(#'DSAPrivateKey'{}) -> - true; -is_key(#'RSAPrivateKey'{}) -> - true; -is_key(#'ECPrivateKey'{}) -> - true; -is_key(_) -> - false. - der_to_pem(File, Entries) -> PemBin = public_key:pem_encode(Entries), file:write_file(File, PemBin). - -default_key_gen() -> - case tls_v1:ecc_curves(0) of - [] -> - [{rsa, 2048, 17}, {rsa, 2048, 17}]; - [_|_] -> - [{namedCurve, hd(tls_v1:ecc_curves(0))}, - {namedCurve, hd(tls_v1:ecc_curves(0))}] - end. - -auth_key_oid(server) -> - ?'id-kp-serverAuth'; -auth_key_oid(client) -> - ?'id-kp-clientAuth'. diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 25b2a2bec0..bb77326751 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 8.2 +SSL_VSN = 8.2.1 diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 7605ac763d..122b476ddb 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -466,8 +466,6 @@ obsolete_1(inviso, _, _) -> {removed,"the inviso application was removed in R16"}; %% Added in R15B01. -obsolete_1(gs, _, _) -> - {removed,"the gs application has been removed; use the wx application instead"}; obsolete_1(ssh, sign_data, 2) -> {removed,"removed in R16A; use public_key:pem_decode/1, public_key:pem_entry_decode/1 " "and public_key:sign/3 instead"}; diff --git a/lib/syntax_tools/src/syntax_tools.app.src b/lib/syntax_tools/src/syntax_tools.app.src index 5c6008a5f0..af50b7495b 100644 --- a/lib/syntax_tools/src/syntax_tools.app.src +++ b/lib/syntax_tools/src/syntax_tools.app.src @@ -18,4 +18,4 @@ {applications, [stdlib]}, {env, []}, {runtime_dependencies, - ["compiler-7.0","erts-8.0","kernel-5.0","stdlib-3.0"]}]}. + ["compiler-7.0","erts-9.0","kernel-5.0","stdlib-3.4"]}]}. diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 2fe42beb03..fb657c2928 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1136,7 +1136,7 @@ ensure_open(Pid, _Options) when is_pid(Pid) -> ensure_open([], _Options) -> {already_open, undefined}; ensure_open(Filename, Options) when is_atom(Filename); is_list(Filename) -> - file:open(Filename, Options). + file:open(Filename, [{encoding, utf8} | Options]). %%%--------------------------------- %%% Fairly generic utility functions diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src index 8beef49bf9..f8c6aa22cb 100644 --- a/lib/tools/src/tools.app.src +++ b/lib/tools/src/tools.app.src @@ -40,7 +40,7 @@ {env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]} ] }, - {runtime_dependencies, ["stdlib-3.1","runtime_tools-1.8.14", + {runtime_dependencies, ["stdlib-3.4","runtime_tools-1.8.14", "kernel-5.4","erts-9.1","compiler-5.0"]} ] }. diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl index affb45b7a6..8fd164a4b3 100644 --- a/lib/tools/test/fprof_SUITE.erl +++ b/lib/tools/test/fprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2016. All Rights Reserved. +%% Copyright Ericsson AB 2001-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ %% Test suites -export([stack_seq/1, tail_seq/1, create_file_slow/1, spawn_simple/1, imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1, - cpu_create_file_slow/1]). + cpu_create_file_slow/1, unicode/1]). %% Other exports -export([create_file_slow/2]). @@ -59,7 +59,7 @@ all() -> false -> [stack_seq, tail_seq, create_file_slow, spawn_simple, imm_tail_seq, imm_create_file_slow, imm_compile, - cpu_create_file_slow] + cpu_create_file_slow, unicode] end. @@ -533,6 +533,17 @@ cpu_create_file_slow(Config) when is_list(Config) -> TestResult. +unicode(Config) when is_list(Config) -> + DataDir = proplists:get_value(data_dir, Config), + SourceFile = filename:join(DataDir, "fprof_unicode.erl"), + PrivDir = proplists:get_value(priv_dir, Config), + AnalysisFile = filename:join(PrivDir, "fprof_unicode.analysis"), + {ok, fprof_unicode} = compile:file(SourceFile, [{outdir, PrivDir}]), + true = code:add_path(PrivDir), + fprof:apply(fprof_unicode, t, []), + ok = fprof:profile(dump, AnalysisFile), + ok = fprof:analyse(dest, AnalysisFile). + %%%--------------------------------------------------------------------- %%% Functions to test %%%--------------------------------------------------------------------- diff --git a/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl new file mode 100644 index 0000000000..8b58efc5fe --- /dev/null +++ b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl @@ -0,0 +1,36 @@ +-module(fprof_unicode). + +-export([t/0, 'кирилли́ческий атом'/0, annan/0, c_break/1, + 'кирилли́ческий атомB'/1]). + +t() -> + _Atom = 'кирилли́ческий атом', + 'кирилли́ческий атом'(). + +'кирилли́ческий атом'() -> + 'кирилли́ческий атом'('кирилли́ческий атом'). + +'кирилли́ческий атом'(_Atom) -> + self() ! 'кирилли́ческий атом', + G = fun (X) -> + catch foo:bar() + end, + G("кирилли́ческий атом"), % line 17 + Pid = spawn_link(fun() -> waiting() end), + true = register('кирилли́ческий атом', Pid), + F = fun() -> 'кирилли́ческий атом' end, + F(). + +annan() -> + foo. + +waiting() -> + receive + X -> X + end. + +c_break(_B) -> + true. + +'кирилли́ческий атомB'(_B) -> + true. diff --git a/make/fakefop b/make/fakefop index 7beeddf0a5..7a34c4faf1 100755 --- a/make/fakefop +++ b/make/fakefop @@ -22,13 +22,13 @@ # Author: Tuncer Ayaz # -if [ $# -lt 6 ] +if [ $# -lt 8 ] then - echo "Usage: fakefop -c IGNORED -fo IGNORED -pdf OUTFILE" + echo "Usage: fakefop -c IGNORED -cache IGNORED -fo IGNORED -pdf OUTFILE" exit 1 fi -OUTFILE=$6 +OUTFILE=$8 echo -n -e '%PDF-1.4\n%\0342\0343\0317\0323\n\n' > $OUTFILE @@ -87,12 +87,12 @@ endobj xref 0 6 -0000000000 65536 f -0000000016 00000 n -0000000070 00000 n -0000000136 00000 n -0000000291 00000 n -0000000410 00000 n +0000000000 65536 f +0000000016 00000 n +0000000070 00000 n +0000000136 00000 n +0000000291 00000 n +0000000410 00000 n trailer << diff --git a/make/otp.mk.in b/make/otp.mk.in index 4232d37c2e..1d538fa528 100644 --- a/make/otp.mk.in +++ b/make/otp.mk.in @@ -139,7 +139,7 @@ endif # .PRECIOUS: %.erl %.fo -## Uncomment these lines and add .idl to suffixes above to have erlc +## Uncomment these lines and add .idl to suffixes above to have erlc ## eat IDL files ##$(EGEN)/%.erl: $(ESRC)/%.idl ## $(ERLC) $(IDL_FLAGS) $< @@ -239,7 +239,7 @@ ifeq ($(PDFCOLOR),) PDFCOLOR = \#960003 endif -# HTML & GIF files that always are generated and must be delivered +# HTML & GIF files that always are generated and must be delivered SGML_COLL_FILES = $(SGML_APPLICATION_FILES) $(SGML_PART_FILES) XML_COLL_FILES = $(XML_APPLICATION_FILES) $(XML_PART_FILES) DEFAULT_HTML_FILES = \ @@ -327,5 +327,4 @@ $(MAN9DIR)/%.9: %.xml escript $(DOCGEN)/priv/bin/codeline_preprocessing.escript $< $@ .fo.pdf: - $(FOP) -c $(FOP_CONFIG) -fo $< -pdf $@ - + $(FOP) -c $(FOP_CONFIG) -cache $(ERL_TOP)/make/$(TARGET)/fop-fonts.cache -fo $< -pdf $@ diff --git a/system/doc/design_principles/des_princ.xml b/system/doc/design_principles/des_princ.xml index af5904ce78..e21f2a7f4e 100644 --- a/system/doc/design_principles/des_princ.xml +++ b/system/doc/design_principles/des_princ.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2016</year> + <year>1997</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/oam/oam_intro.xml b/system/doc/oam/oam_intro.xml index b4142b3cc5..d3867f03ca 100644 --- a/system/doc/oam/oam_intro.xml +++ b/system/doc/oam/oam_intro.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2016</year> + <year>1997</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> |