File 6580-inet_dns-support-TSIG.patch of Package erlang
From 2473a414da546440636e722dd794c2e12ad892f0 Mon Sep 17 00:00:00 2001
From: Alexander Clouter <alex@digriz.org.uk>
Date: Wed, 9 Aug 2023 16:38:55 +0100
Subject: [PATCH 10/10] inet_dns: support TSIG
---
lib/kernel/src/Makefile | 2 +
lib/kernel/src/inet_dns.erl | 86 ++-
lib/kernel/src/inet_dns.hrl | 48 ++
lib/kernel/src/inet_dns_tsig.erl | 319 +++++++++++
lib/kernel/src/inet_res.erl | 13 +-
lib/kernel/src/kernel.app.src | 1 +
lib/kernel/test/inet_res_SUITE.erl | 195 ++++++-
.../inet_res_SUITE_data/otptest/knot_inc.conf | 13 +-
.../inet_res_SUITE_data/otptest/otptest.zone | 507 ++++++++++++++++++
9 files changed, 1178 insertions(+), 6 deletions(-)
create mode 100644 lib/kernel/src/inet_dns_tsig.erl
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index f67044f5e7..929f1d2c4e 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -100,6 +100,7 @@ MODULES = \
inet_config \
inet_db \
inet_dns \
+ inet_dns_tsig \
inet_gethost_native \
inet_hosts \
inet_parse \
@@ -266,6 +267,7 @@ $(EBIN)/inet6_sctp.beam: inet_int.hrl
$(EBIN)/inet_config.beam: inet_config.hrl ../include/inet.hrl
$(EBIN)/inet_db.beam: ../include/inet.hrl inet_int.hrl inet_res.hrl inet_dns.hrl inet_config.hrl
$(EBIN)/inet_dns.beam: inet_int.hrl inet_dns.hrl inet_dns_record_adts.hrl
+$(EBIN)/inet_dns_tsig.beam: inet_dns.hrl
$(EBIN)/inet_gethost_native.beam: ../include/inet.hrl
$(EBIN)/inet_hosts.beam: ../include/inet.hrl
$(EBIN)/inet_parse.beam: ../include/file.hrl
diff --git a/lib/kernel/src/inet_dns.erl b/lib/kernel/src/inet_dns.erl
index 6228ca9790..c65546a7e5 100644
--- a/lib/kernel/src/inet_dns.erl
+++ b/lib/kernel/src/inet_dns.erl
@@ -33,8 +33,10 @@
%% RFC 6762: Multicast DNS
%% RFC 6891: Extension Mechanisms for DNS (EDNS0)
%% RFC 7553: The Uniform Resource Identifier (URI) DNS Resource Record
+%% RFC 8945: Secret Key Transaction Authentication for DNS (TSIG)
-export([decode/1, encode/1]).
+-export([decode_algname/1, encode_algname/1]).
-import(lists, [reverse/1]).
@@ -253,6 +255,28 @@ decode_rr_section(Opcode, Bin, N, Buffer, RRs) ->
z = Z,
data = D,
do = DnssecOk};
+ ?S_TSIG ->
+ %% RFC 8945: 5.2. FORMERR if not last
+ %% RFC 8945: 5.2. FORMERR if more than one dns_rr_tsig
+ %% (...covered by being last)
+ Rest =/= <<>> andalso throw(?DECODE_ERROR),
+ {DR,AlgName} = decode_name(D, Buffer),
+ ?MATCH_ELSE_DECODE_ERROR(
+ DR,
+ <<Now:48, Fudge:16, MACSize:16, MAC:MACSize/binary,
+ OriginalId:16, Error:16,
+ OtherLen:16, OtherData:OtherLen/binary>>,
+ #dns_rr_tsig{
+ domain = Name,
+ type = Type,
+ offset = byte_size(Buffer) - byte_size(Bin),
+ algname = AlgName,
+ now = Now,
+ fudge = Fudge,
+ mac = MAC,
+ original_id = OriginalId,
+ error = Error,
+ other_data = OtherData});
_ ->
{Class,CacheFlush} = decode_class(C),
Data = if
@@ -347,7 +371,22 @@ encode_res_section(
DO = case DnssecOk of true -> 1; false -> 0 end,
encode_res_section_rr(
Opcode, Bin, Comp, Rs, DName, ?S_OPT, UdpPayloadSize, false,
- <<ExtRCode,Version,DO:1,Z:15>>, Data).
+ <<ExtRCode,Version,DO:1,Z:15>>, Data);
+encode_res_section(
+ Opcode, Bin, Comp,
+ [#dns_rr_tsig{
+ domain = DName,
+ algname = AlgName,
+ now = Now,
+ fudge = Fudge,
+ mac = MAC,
+ original_id = OriginalId,
+ error = Error,
+ other_data = OtherData}]) ->
+ Data = {AlgName,Now,Fudge,MAC,OriginalId,Error,OtherData},
+ encode_res_section_rr(
+ Opcode, Bin, Comp, [], DName, ?S_TSIG, ?S_ANY, false,
+ <<0:32/signed>>, Data).
encode_res_section_rr(
Opcode, Bin0, Comp0, Rs, DName, Type, Class, CacheFlush, TTL, Data) ->
@@ -399,6 +438,7 @@ decode_type(Type) ->
?T_UID -> ?S_UID;
?T_GID -> ?S_GID;
?T_UNSPEC -> ?S_UNSPEC;
+ ?T_TSIG -> ?S_TSIG;
?T_IXFR -> ?S_IXFR;
?T_AXFR -> ?S_AXFR;
?T_MAILB -> ?S_MAILB;
@@ -441,6 +481,7 @@ encode_type(Type) ->
?S_UID -> ?T_UID;
?S_GID -> ?T_GID;
?S_UNSPEC -> ?T_UNSPEC;
+ ?S_TSIG -> ?T_TSIG;
?S_IXFR -> ?T_IXFR;
?S_AXFR -> ?T_AXFR;
?S_MAILB -> ?T_MAILB;
@@ -833,6 +874,17 @@ encode_data(Comp, _, ?S_CAA, Data)->
_ ->
{encode_txt(Data),Comp}
end;
+encode_data(Comp, _, ?S_TSIG, Data)->
+ {AlgName,Now,Fudge,MAC,OriginalId,Error,OtherData} = Data,
+ %% Bypass name compression (RFC 8945, section 4.2)
+ {AlgNameEncoded,_} = encode_name(gb_trees:empty(), 0, AlgName),
+ MACSize = byte_size(MAC),
+ OtherLen = byte_size(OtherData),
+ DataB = <<AlgNameEncoded/binary,
+ Now:48, Fudge:16, MACSize:16, MAC:MACSize/binary,
+ OriginalId:16, Error:16,
+ OtherLen:16, OtherData:OtherLen/binary>>,
+ {DataB,Comp};
%%
%% sofar unknown or non standard
encode_data(Comp, _Pos, Type, Data) when is_integer(Type) ->
@@ -972,3 +1024,35 @@ encode_loc_size(X)
Multiplier = round(math:pow(10, Exponent)),
Base = (X + Multiplier - 1) div Multiplier,
<<Base:4, Exponent:4>>.
+
+decode_algname(AlgName) ->
+ case AlgName of
+ ?T_TSIG_HMAC_MD5 -> ?S_TSIG_HMAC_MD5;
+ ?T_TSIG_GSS_TSIG -> ?S_TSIG_GSS_TSIG;
+ ?T_TSIG_HMAC_SHA1 -> ?S_TSIG_HMAC_SHA1;
+ ?T_TSIG_HMAC_SHA1_96 -> ?S_TSIG_HMAC_SHA1_96;
+ ?T_TSIG_HMAC_SHA224 -> ?S_TSIG_HMAC_SHA224;
+ ?T_TSIG_HMAC_SHA256 -> ?S_TSIG_HMAC_SHA256;
+ ?T_TSIG_HMAC_SHA256_128 -> ?S_TSIG_HMAC_SHA256_128;
+ ?T_TSIG_HMAC_SHA384 -> ?S_TSIG_HMAC_SHA384;
+ ?T_TSIG_HMAC_SHA384_192 -> ?S_TSIG_HMAC_SHA384_192;
+ ?T_TSIG_HMAC_SHA512 -> ?S_TSIG_HMAC_SHA512;
+ ?T_TSIG_HMAC_SHA512_256 -> ?S_TSIG_HMAC_SHA512_256;
+ _ -> AlgName % raw unknown algname
+ end.
+
+encode_algname(Alg) ->
+ case Alg of
+ ?S_TSIG_HMAC_MD5 -> ?T_TSIG_HMAC_MD5;
+ ?S_TSIG_GSS_TSIG -> ?T_TSIG_GSS_TSIG;
+ ?S_TSIG_HMAC_SHA1 -> ?T_TSIG_HMAC_SHA1;
+ ?S_TSIG_HMAC_SHA1_96 -> ?T_TSIG_HMAC_SHA1_96;
+ ?S_TSIG_HMAC_SHA224 -> ?T_TSIG_HMAC_SHA224;
+ ?S_TSIG_HMAC_SHA256 -> ?T_TSIG_HMAC_SHA256;
+ ?S_TSIG_HMAC_SHA256_128 -> ?T_TSIG_HMAC_SHA256_128;
+ ?S_TSIG_HMAC_SHA384 -> ?T_TSIG_HMAC_SHA384;
+ ?S_TSIG_HMAC_SHA384_192 -> ?T_TSIG_HMAC_SHA384_192;
+ ?S_TSIG_HMAC_SHA512 -> ?T_TSIG_HMAC_SHA512;
+ ?S_TSIG_HMAC_SHA512_256 -> ?T_TSIG_HMAC_SHA512_256;
+ Alg when is_list(Alg) -> Alg % raw unknown algname
+ end.
diff --git a/lib/kernel/src/inet_dns.hrl b/lib/kernel/src/inet_dns.hrl
index 17151fbb6a..d3b5930b4c 100644
--- a/lib/kernel/src/inet_dns.hrl
+++ b/lib/kernel/src/inet_dns.hrl
@@ -45,6 +45,10 @@
-define(NOTAUTH, 9). %% server not authoritative for zone (DDNS)
-define(NOTZONE, 10). %% name not contained in zone (DDNS)
-define(BADVERS, 16). %% bad version EDNS pseudo-rr RFC6891: 6.1.3
+-define(BADSIG, 16). %% TSIG Signature Failure (TSIG)
+-define(BADKEY, 17). %% Key not recognized (TSIG)
+-define(BADTIME, 18). %% Signature out of time window (TSIG)
+-define(BADTRUNC, 22). %% Bad Truncation (TSIG)
%%
%% Type values for resources and queries
@@ -80,6 +84,7 @@
-define(T_UID, 101). %% user ID
-define(T_GID, 102). %% group ID
-define(T_UNSPEC, 103). %% Unspecified format (binary data)
+-define(T_TSIG, 250). %% transaction signature
-define(T_IXFR, 251). %% incremental zone transfer
-define(T_AXFR, 252). %% zone transfer
-define(T_MAILB, 253). %% transfer mailbox records
@@ -124,6 +129,7 @@
-define(S_UID, uid). %% user ID
-define(S_GID, gid). %% group ID
-define(S_UNSPEC, unspec). %% Unspecified format (binary data)
+-define(S_TSIG, tsig). %% transaction signature
-define(S_IXFR, ixfr). %% incremental zone transfer
-define(S_AXFR, axfr). %% zone transfer
-define(S_MAILB, mailb). %% transfer mailbox records
@@ -143,6 +149,33 @@
-define(C_NONE, 254). %% for DDNS (RFC2136, section 2.4)
-define(C_ANY, 255). %% wildcard match
+%%
+%% TSIG Algorithms and Identifiers (RFC8945, section 6)
+%%
+-define(T_TSIG_HMAC_MD5, "HMAC-MD5.SIG-ALG.REG.INT").
+-define(T_TSIG_GSS_TSIG, "gss-tsig").
+-define(T_TSIG_HMAC_SHA1, "hmac-sha1").
+-define(T_TSIG_HMAC_SHA1_96, "hmac-sha1_96").
+-define(T_TSIG_HMAC_SHA224, "hmac-sha224").
+-define(T_TSIG_HMAC_SHA256, "hmac-sha256").
+-define(T_TSIG_HMAC_SHA256_128, "hmac-sha256-128").
+-define(T_TSIG_HMAC_SHA384, "hmac-sha384").
+-define(T_TSIG_HMAC_SHA384_192, "hmac-sha384-192").
+-define(T_TSIG_HMAC_SHA512, "hmac-sha512").
+-define(T_TSIG_HMAC_SHA512_256, "hmac-sha512-256").
+% map mostly to crypto:hmac_hash_algorithm()
+-define(S_TSIG_HMAC_MD5, md5).
+-define(S_TSIG_GSS_TSIG, gss_tsig).
+-define(S_TSIG_HMAC_SHA1, sha).
+-define(S_TSIG_HMAC_SHA1_96, {sha,96}).
+-define(S_TSIG_HMAC_SHA224, sha224).
+-define(S_TSIG_HMAC_SHA256, sha256).
+-define(S_TSIG_HMAC_SHA256_128, {sha256,128}).
+-define(S_TSIG_HMAC_SHA384, sha384).
+-define(S_TSIG_HMAC_SHA384_192, {sha384,192}).
+-define(S_TSIG_HMAC_SHA512, sha512).
+-define(S_TSIG_HMAC_SHA512_256, {sha512,256}).
+
%%
%% Structure for query header, the order of the fields is machine and
%% compiler dependent, in our case, the bits within a byte are assignd
@@ -206,6 +239,21 @@
do = false %% RFC6891(6.1.3 DO)
}).
+-record(dns_rr_tsig, %% TSIG RR OPT (RFC8945), dns_rr{type=tsig}
+ {
+ domain = "", %% name of the key
+ type = tsig,
+ offset, %% position of RR in packet
+ %% RFC8945(4.2 TSIG Record Format)
+ algname,
+ now,
+ fudge,
+ mac,
+ original_id = #dns_header{}#dns_header.id,
+ error = #dns_header{}#dns_header.rcode,
+ other_data = <<>>
+ }).
+
-record(dns_query,
{
domain, %% query domain
diff --git a/lib/kernel/src/inet_dns_tsig.erl b/lib/kernel/src/inet_dns_tsig.erl
new file mode 100644
index 0000000000..46bd05b2b0
--- /dev/null
+++ b/lib/kernel/src/inet_dns_tsig.erl
@@ -0,0 +1,319 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2023. 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.
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+-module(inet_dns_tsig).
+
+%% DNS TSIG handling
+%%
+%% RFC 8945: Secret Key Transaction Authentication for DNS (TSIG)
+
+%% WARNING: in the spirit of inet_dns.erl, this module only handles the
+%% cryptographic operations and does not absolve you of your responsibities
+%% that include:
+%% * implement a truncation policy as per RFC8945, section 5.2
+%% * verifying that for TSIG over TCP the last message contains a TSIG RR
+%% * truncated messages must include the TSIG RR as per RFC8945, section 5.3
+%% * if running as a server, generate suitable error responses
+%% as per RFC8945, section 5.2
+
+-export([init/1, sign/2, sign/3, verify/3]).
+
+-include("inet_dns.hrl").
+
+-define(FUDGE_DEFAULT, 300). % RFC8945, section 10
+-define(MAC_SIZE_MIN, 10). % RFC8945, section 5.2.2.1
+-define(TTL, 0).
+-define(NOW, (os:system_time(seconds))). % RFC8945, section 5.2.3
+
+-define(ALG_DEFAULT, sha256). % RFC8945, section 6
+-define(ALGS_SUPPORTED, [md5, sha, sha224, ?ALG_DEFAULT, sha384, sha512]).
+-type tsig_algs() :: md5 | sha | sha224 | ?ALG_DEFAULT | sha384 | sha512.
+-type tsig_alg() :: {tsig_algs(),?MAC_SIZE_MIN..65535}.
+
+-type tsig_key() :: {string(),iodata()}.
+-type tsig_error() :: ?BADSIG | ?BADKEY | ?BADTIME | ?BADTRUNC.
+
+-record(
+ tsig_state,
+ {key = [] :: tsig_key() | list(tsig_key()),
+ alg = ?ALG_DEFAULT :: tsig_alg(), % client only
+ fudge = ?FUDGE_DEFAULT :: 0..65535,
+
+ qr = 0 :: 0..100,
+ %% 0 (false): request, 1+ (true): response
+ %% this value is overloaded to handle TSIG
+ %% over TCP where we need to accept up to
+ %% 99 messages without TSIG so each time a
+ %% response with a TSIG RR is received this
+ %% value is reset to 2
+
+ id :: undefined | 0..65535,
+ mac = {?MODULE,undefined} ::
+ {?MODULE,undefined | binary()} | {crypto,crypto:mac_state()}
+}).
+-opaque tsig_state() :: #tsig_state{}.
+-export_type([tsig_state/0]).
+
+-spec init(proplists:proplist()) -> tsig_state().
+init(Config) ->
+ Key0 = proplists:get_value(keys, Config, []), % server passes in keys
+ Key = proplists:get_value(key, Config, Key0), % client passes in key
+ true = is_tuple(Key) orelse Key =/= [],
+ Alg = case proplists:get_value(alg, Config, ?ALG_DEFAULT) of
+ {A,S} when is_atom(A), is_integer(S) ->
+ true = lists:member(A, ?ALGS_SUPPORTED)
+ andalso
+ S >= ?MAC_SIZE_MIN
+ andalso
+ S >= maps:get(size, crypto:hash_info(A)) div 2,
+ {A,S};
+ A when is_atom(A) ->
+ true = lists:member(A, ?ALGS_SUPPORTED),
+ {A,maps:get(size, crypto:hash_info(A))}
+ end,
+ Fudge = proplists:get_value(fudge, Config, ?FUDGE_DEFAULT),
+ true = is_integer(Fudge) andalso Fudge >= 0 andalso Fudge =< 65535,
+ #tsig_state{ key = Key, alg = Alg, fudge = Fudge }.
+
+
+-spec sign(binary(), tsig_state()) -> {ok,binary(),tsig_state()}.
+sign(Pkt, TS) ->
+ sign(Pkt, TS, ?NOERROR).
+
+-spec sign(binary(), tsig_state(), tsig_error() | ?NOERROR) ->
+ {ok,binary(),tsig_state()}.
+sign(
+ Pkt = <<Hdr:10/binary, Rest/binary>>,
+ TS = #tsig_state{ id = TSId, qr = TSQR },
+ Error) ->
+ case Hdr of
+ %% client uses this
+ <<Id:16, QR:1, _:15, _/binary>>
+ when QR == 0, TSId == undefined ->
+ sign(Pkt, TS#tsig_state{ id = Id }, Error, Hdr, Rest);
+ %%
+ %% client and server use this
+ <<_Id:16, QR:1, _:15, _/binary>>
+ when QR == 0, TSQR == 0;
+ QR == 1, TSQR >= 1 ->
+ sign(Pkt, TS, Error, Hdr, Rest)
+ end.
+
+sign(Pkt, TS, Error, Hdr, <<ARCount:16, Content/binary>>) ->
+ {Name,_Secret} = TS#tsig_state.key,
+ {Alg,_MACSize} = TS#tsig_state.alg,
+ Now = ?NOW,
+ OtherData = otherdata(Error, Now),
+ MAC = mac(Pkt, TS, Error, Now, OtherData),
+ TSigRR =
+ #dns_rr_tsig{
+ domain = Name,
+ algname = inet_dns:encode_algname(Alg),
+ now = Now,
+ fudge = TS#tsig_state.fudge,
+ mac = MAC,
+ original_id = TS#tsig_state.id,
+ error = Error,
+ other_data = OtherData},
+ %% for simplicity, and to avoid export hell, we encode a skeleton packet and
+ %% extract our TSIG RR directly from it
+ <<_:12/binary, TSigRRBin/binary>> =
+ inet_dns:encode(
+ #dns_rec{ header = #dns_header{}, arlist = [TSigRR]}),
+ TSQR = TS#tsig_state.qr,
+ {ok,
+ <<Hdr/binary, (ARCount + 1):16, Content/binary, TSigRRBin/binary>>,
+ TS#tsig_state{ qr = TSQR + 1, mac = {?MODULE,MAC} }}.
+
+
+%% this function needs to work with the original response binary as the MAC
+%% calculation is affected by each DNS implementation having their own varying
+%% name compression algorithm
+-spec verify(binary(), #dns_rec{}, tsig_state()) ->
+ {ok,tsig_state()} |
+ {error,formerr | {notauth,badkey | badsig | badtime}}.
+verify(Pkt, Response, TS) ->
+ try do_verify(Pkt, Response, TS) of
+ R ->
+ R
+ catch
+ Reason ->
+ {error,Reason}
+ end.
+
+%% server uses this
+do_verify(Pkt,
+ Response = #dns_rec{
+ header = #dns_header{ qr = QR },
+ arlist = ARList },
+ TS0 = #tsig_state{ id = TSId })
+ when QR == false, TSId == undefined ->
+ ARList == [] andalso throw({noauth,badsig}),
+ #dns_rr_tsig{
+ domain = Name,
+ algname = AlgName,
+ mac = MAC,
+ original_id = OriginalId,
+ error = Error
+ } = lists:last(ARList),
+ Key = lists:keyfind(Name, 1, TS0#tsig_state.key),
+ Key == false andalso throw({notauth,badkey}),
+ {Alg,AlgSize} = case inet_dns:decode_algname(AlgName) of
+ {A,S} ->
+ {A,S};
+ A ->
+ {A,maps:get(size, crypto:hash_info(A))}
+ end,
+ %% RFC8945, section 5.2.2.1: MAC Truncation
+ MACSize = if
+ Error == ?BADSIG; Error == ?BADKEY ->
+ AlgSize;
+ true ->
+ byte_size(MAC)
+ end,
+ lists:member(Alg, ?ALGS_SUPPORTED) orelse throw({notauth,badkey}),
+ MACValid = MACSize >= ?MAC_SIZE_MIN
+ andalso
+ MACSize >= AlgSize div 2
+ andalso
+ MACSize =< AlgSize,
+ MACValid orelse throw(formerr),
+ TS = TS0#tsig_state{ alg = {Alg,AlgSize}, key = Key, id = OriginalId },
+ do_verify(Pkt, Response, TS);
+%%
+%% client and server use this
+do_verify(Pkt = <<_Id:16, QR:1, _:15, _/binary>>,
+ Response = #dns_rec{ arlist = ARList },
+ TS = #tsig_state{ qr = TSQR })
+ when QR == TSQR; QR == 1 andalso TSQR >= 2 ->
+ case ARList =/= [] andalso lists:last(ARList) of
+ %% RFC8945, section 5.3.1: TSIG on TCP Connections
+ false when TSQR == 3 -> % not 2 as we must start with a TSIG RR
+ MAC0 = mac0(TS),
+ %% TS#tsig_state.mac is {?MODULE,binary()} (Previous MAC)
+ MACN0 = macN(TS#tsig_state.mac, TS#tsig_state{ mac = MAC0 }),
+ MACN = macN(Pkt, TS#tsig_state{ mac = MACN0 }),
+ {ok,TS#tsig_state{ qr = TSQR + 1, mac = MACN }};
+ false when TSQR >= 4, TSQR =< 99 ->
+ MACN = macN(Pkt, TS),
+ {ok,TS#tsig_state{ qr = TSQR + 1, mac = MACN }};
+ TSigRR = #dns_rr_tsig{} ->
+ do_verify(Pkt, Response, TS, TSigRR);
+ false ->
+ {error,{notauth,badsig}}
+ end.
+
+do_verify(Pkt, _Response, TS, TSigRR) ->
+ Now = ?NOW,
+ #dns_rr_tsig{
+ offset = Offset,
+ now = NowSigned,
+ fudge = Fudge,
+ mac = MAC,
+ error = Error,
+ other_data = OtherData
+ } = TSigRR,
+ PktS = iolist_to_binary([
+ <<(TS#tsig_state.id):16>>,
+ binary:part(Pkt, {2,8}),
+ begin
+ <<ARC:16>> = binary:part(Pkt, {10,2}),
+ <<(ARC - 1):16>>
+ end,
+ binary:part(Pkt, {12,Offset - 12})
+ ]),
+ MACCalc = if
+ element(1, TS#tsig_state.mac) == ?MODULE ->
+ mac(PktS, TS, Error, Now, OtherData);
+ %% RFC8945, section 5.3.1: TSIG on TCP Connections
+ true ->
+ mac(TS, Error, Now, OtherData)
+ end,
+ if
+ %% RFC8945, section 5.2 - MUST check time after MAC
+ MAC == MACCalc, NowSigned - Fudge < Now, NowSigned + Fudge > Now ->
+ QR = if TS#tsig_state.qr == 0 -> 1; true -> 2 end,
+ {ok,TS#tsig_state{ qr = QR, mac = {?MODULE,MAC} }};
+ MAC == MACCalc ->
+ {error,{notauth,badtime}};
+ true ->
+ {error,{notauth,badsig}}
+ end.
+
+%% similar to inet_dns:encode_name/3 but without compression
+encode_name(Name) ->
+ iolist_to_binary([
+ [ <<(byte_size(L)):8, L/binary>>
+ || L <- binary:split(list_to_binary(Name), <<".">>, [global]) ],
+ <<0:8>>
+ ]).
+
+otherdata(?BADTIME, Now) -> <<Now:48>>;
+otherdata(_Error, _Now) -> <<>>.
+
+mac0(TS = #tsig_state{ mac = {?MODULE,MAC} }) ->
+ {_Name,Secret} = TS#tsig_state.key,
+ {Alg,_MACSize} = TS#tsig_state.alg,
+ MACState = crypto:mac_init(hmac, Alg, Secret),
+ {crypto,if
+ %% RFC8945, section 5.3.1: TSIG on TCP Connections
+ is_binary(MAC) ->
+ MS = byte_size(MAC),
+ crypto:mac_update(MACState, [<<MS:16>>, MAC]);
+ true ->
+ MACState
+ end}.
+
+macN({?MODULE,MAC}, #tsig_state{ mac = {crypto,MACState} }) ->
+ {crypto,crypto:mac_update(MACState, MAC)};
+macN(Pkt, TS = #tsig_state{ mac = {crypto,MACState} }) ->
+ {crypto,crypto:mac_update(MACState, [
+ <<(TS#tsig_state.id):16>>,
+ binary:part(Pkt, {2,byte_size(Pkt) - 2})
+ ])}.
+
+%% RFC8945, section 5.3.2: Generation of TSIG on Error Returns
+mac(_TS, Error, _Now, _OtherData)
+ when Error == ?BADSIG; Error == ?BADKEY ->
+ <<>>;
+mac(TS = #tsig_state{ mac = {crypto,MACState0} }, Error, Now, OtherData) ->
+ {Name,_Secret} = TS#tsig_state.key,
+ {Alg,MACSize} = TS#tsig_state.alg,
+ Fudge = TS#tsig_state.fudge,
+ OtherLen = byte_size(OtherData),
+ MACState = crypto:mac_update(MACState0, if
+ TS#tsig_state.qr =< 1 ->
+ [
+ %% TSIG RR
+ encode_name(Name), <<?C_ANY:16>>, <<?TTL:32/signed>>,
+ %% TSIG RDATA
+ encode_name(inet_dns:encode_algname(Alg)),
+ <<Now:48, Fudge:16, Error:16, OtherLen:16>>,
+ OtherData
+ ];
+ %% RFC8945, section 5.3.1: TSIG on TCP Connections
+ true ->
+ <<Now:48, Fudge:16>>
+ end),
+ crypto:mac_finalN(MACState, MACSize).
+
+mac(Pkt, TS, Error, Now, OtherData) ->
+ MAC0 = mac0(TS),
+ MACN = macN(Pkt, TS#tsig_state{ mac = MAC0 }),
+ mac(TS#tsig_state{ mac = MACN }, Error, Now, OtherData).
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index f0d2f21364..091ebef91c 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1094,11 +1094,16 @@ decode_answer(Answer, Q_Msg, Verbose) ->
case inet_dns:decode(Answer) of
{ok, #dns_rec{header = H, arlist = ARList} = Msg} ->
?verbose(Verbose, "Got reply: ~p~n", [dns_msg(Msg)]),
+ T = case lists:keyfind(dns_rr_tsig, 1, ARList) of
+ false -> false;
+ #dns_rr_tsig{error=?NOERROR} -> false;
+ #dns_rr_tsig{error=TsigError} -> TsigError
+ end,
E = case lists:keyfind(dns_rr_opt, 1, ARList) of
false -> 0;
#dns_rr_opt{ext_rcode=ExtRCode} -> ExtRCode
end,
- RCode = (E bsl 4) bor H#dns_header.rcode,
+ RCode = T orelse (E bsl 4) bor H#dns_header.rcode,
case RCode of
?NOERROR -> decode_answer_noerror(Q_Msg, Msg, H);
?FORMERR -> {error,{qfmterror,Msg}};
@@ -1111,7 +1116,11 @@ decode_answer(Answer, Q_Msg, Verbose) ->
?NXRRSET -> {error,{nxrrset,Msg}};
?NOTAUTH -> {error,{noauth,Msg}};
?NOTZONE -> {error,{nozone,Msg}};
- ?BADVERS -> {error,{badvers,Msg}};
+ ?BADVERS when not T -> {error,{badvers,Msg}};
+ ?BADSIG -> {error,{badsig,Msg}};
+ ?BADKEY -> {error,{badkey,Msg}};
+ ?BADTIME -> {error,{badtime,Msg}};
+ ?BADTRUNC -> {error,{badtrunc,Msg}};
_ -> {error,{unknown,Msg}}
end;
{error, formerr} = Error ->
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 10705d9d76..4ae0fb6bb5 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -104,6 +104,7 @@
inet,
inet_db,
inet_dns,
+ inet_dns_tsig,
inet_parse,
inet_res,
inet_tcp,
diff --git a/lib/kernel/test/inet_res_SUITE.erl b/lib/kernel/test/inet_res_SUITE.erl
index c69cf934ce..045fdcc83b 100644
--- a/lib/kernel/test/inet_res_SUITE.erl
+++ b/lib/kernel/test/inet_res_SUITE.erl
@@ -35,7 +35,7 @@
edns0/1, edns0_multi_formerr/1, txt_record/1, files_monitor/1,
nxdomain_reply/1, last_ms_answer/1, intermediate_error/1,
servfail_retry_timeout_default/1, servfail_retry_timeout_1000/1,
- label_compression_limit/1, update/1
+ label_compression_limit/1, update/1, tsig_client/1, tsig_server/1
]).
-export([
gethostbyaddr/0, gethostbyaddr/1,
@@ -77,7 +77,7 @@ all() ->
nxdomain_reply, last_ms_answer,
intermediate_error,
servfail_retry_timeout_default, servfail_retry_timeout_1000,
- label_compression_limit, update,
+ label_compression_limit, update, tsig_client, tsig_server,
gethostbyaddr, gethostbyaddr_v6, gethostbyname,
gethostbyname_v6, getaddr, getaddr_v6, ipv4_to_ipv6,
host_and_addr].
@@ -134,6 +134,7 @@ zone_dir(TC) ->
nxdomain_reply -> otptest;
last_ms_answer -> otptest;
update -> otptest;
+ tsig_client -> otptest;
intermediate_error ->
{internal,
#{rcode => ?REFUSED}};
@@ -1470,6 +1471,196 @@ update(Config) when is_list(Config) ->
ok.
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Tests for TSIG
+
+% note for implementors reading this, the usage of
+% inet_dns_tsig.erl is identical except you do not need
+% to inspect the reponse for the presence of a TSIG RR
+tsig_client(Config) when is_list(Config) ->
+ {NSIP,NSPort} = ns(Config),
+ Domain = "otptest",
+ Request = #dns_rec{
+ header = #dns_header{},
+ qdlist = [#dns_query{ domain = Domain, class = in, type = axfr }]
+ },
+ Pkt = inet_dns:encode(Request),
+
+ Key = {"testkey","ded5ada3-07f2-42b9-84bf-82d30f6795ee"},
+ TS0 = inet_dns_tsig:init([{key,Key}]),
+ {ok,PktS,TS1} = inet_dns_tsig:sign(Pkt, TS0),
+
+ SockOpts = [binary,{active,false},{nodelay,true},{packet,2}],
+ {ok,Sock} = gen_tcp:connect(NSIP, NSPort, SockOpts),
+ ok = gen_tcp:send(Sock, PktS),
+ ok = gen_tcp:shutdown(Sock, write),
+ Recv = fun(Recv, A) ->
+ case gen_tcp:recv(Sock, 0) of
+ {ok,P} ->
+ Recv(Recv, [P|A]);
+ {error,closed} ->
+ lists:reverse(A)
+ end
+ end,
+ PktR = Recv(Recv, []),
+ ok = gen_tcp:close(Sock),
+
+ true = PktR =/= [],
+
+ {_TS,Response} = lists:foldl(fun(P, {T0,R0}) ->
+ {ok,R} = inet_dns:decode(P),
+ {ok,T} = inet_dns_tsig:verify(P, R, T0),
+ {T,R0 ++ [R]}
+ end, {TS1,[]}, PktR),
+
+ % not necessary for the test, but helpful to those using this
+ % to understand how to validate TCP responses, we need to check
+ % that the last message has a TSIG RR (RRC8945, section 5.3.1)
+ % N.B. unnecessary for UDP as handled by inet_dns_tsig:verify()
+ #dns_rec{ arlist = ARList } = lists:last(Response),
+ true = ARList =/= [],
+ #dns_rr_tsig{} = lists:last(ARList),
+
+ % actual implementations would here now consider if the additional
+ % checks described in the WARNING at the top of inet_dns_tsig.erl
+ % are applicable to their use case and if so implement them
+ ok.
+
+tsig_server(Config) when is_list(Config) ->
+ case os:find_executable("dig") of
+ false ->
+ case os:find_executable("drill") of
+ false ->
+ {skip, "Cannot find executable: dig|drill"};
+ Drill ->
+ tsig_server(Config, Drill)
+ end;
+ Dig ->
+ tsig_server(Config, Dig)
+ end.
+%%
+tsig_server(_Config, DigDrill) ->
+ Domain = "otptest",
+
+ Key = {"testkey","b0b8006a-04ad-4a96-841a-a4eae78011a1"},
+ Keys0 = [Key,{"grease0",""},{"grease1",""},{"grease2",""}],
+ Rand = [ rand:uniform() || _ <- lists:seq(1, length(Keys0)) ],
+ {_,Keys} = lists:unzip(lists:keysort(1, lists:zip(Rand, Keys0))),
+ TS0 = inet_dns_tsig:init([{keys,Keys}]),
+
+ SockOpts = [binary,{active,false},{nodelay,true},{packet,2}],
+ {ok,LSock} = gen_tcp:listen(0, [{ip,{127,0,0,1}}|SockOpts]),
+ {ok,LPort} = inet:port(LSock),
+
+ _ = process_flag(trap_exit, true),
+ {_, MRef} =
+ spawn_opt(
+ fun() ->
+ KeyName = element(1, Key),
+ KeySecret = base64:encode_to_string(element(2, Key)),
+ Command = DigDrill ++
+ " -p " ++ integer_to_list(LPort) ++
+ " -y hmac-sha256:" ++ KeyName ++ ":" ++ KeySecret ++
+ " " ++ Domain ++ ". @127.0.0.1 AXFR IN",
+ Opts = [in,eof,exit_status,stderr_to_stdout,hide],
+ Port = erlang:open_port({spawn,Command}, Opts),
+ Collect =
+ fun C(A) ->
+ receive
+ {Port,{data,B}} ->
+ C([B|A]);
+ {Port,eof} ->
+ C(A);
+ {Port,{exit_status,Status}} ->
+ {ok,{Status,lists:reverse(A)}};
+ {Port,closed} ->
+ {error,closed}
+ after 1000 ->
+ {error,timeout}
+ end
+ end,
+ ClientResult = Collect([]),
+ true = erlang:port_close(Port),
+ exit({done,ClientResult})
+ end, [link,monitor]),
+
+ Result =
+ case gen_tcp:accept(LSock, 5000) of
+ {ok,Sock} ->
+ try
+ ok = gen_tcp:close(LSock),
+ tsig_server(Domain, TS0, Sock)
+ of
+ _ ->
+ gen_tcp:close(Sock)
+ catch
+ Class : Reason : Stacktrace ->
+ _ = catch gen_tcp:close(Sock),
+ {Class,Reason,Stacktrace}
+ end;
+ Error ->
+ _ = catch gen_tcp:close(LSock),
+ Error
+ end,
+
+ receive
+ {'DOWN',MRef,_,_,{done,{ok,{Code,Output}}}} ->
+ ?P("Output of ~s (exit code ~B):~n~s~n",
+ [DigDrill, Code, Output]),
+ {0,ok} = {Code,Result};
+ {'DOWN',MRef,_,_,CError} ->
+ error({CError,Result})
+ after 1000 ->
+ error({timeout,Result})
+ end.
+
+tsig_server(Domain, TS0, Sock) ->
+ SOAData = {"ns","lsa.soa",1,60,10,300,30},
+ SOA = #dns_rr{ domain = Domain, class = in, type = soa, data = SOAData },
+ PadData = ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"],
+ Padding = #dns_rr{ class = in, type = txt, data = PadData },
+
+ {ok,Pkt} = gen_tcp:recv(Sock, 0),
+ ok = gen_tcp:shutdown(Sock, read),
+
+ {ok,Request} = inet_dns:decode(Pkt),
+ {ok,TS1} = inet_dns_tsig:verify(Pkt, Request, TS0),
+
+ % actual implementations would here now consider if the additional
+ % checks described in the WARNING at the top of inet_dns_tsig.erl
+ % are applicable to their use case and if so implement them
+
+ PktR0 = #dns_rec{
+ header = #dns_header{
+ id = Request#dns_rec.header#dns_header.id,
+ qr = true
+ },
+ qdlist = Request#dns_rec.qdlist
+ },
+
+ Format = "~2.10.0B.padding." ++ Domain,
+ AnList1 = [SOA] ++ [ Padding#dns_rr{
+ domain = io_lib:format(Format, [X]) } ||
+ X <- lists:seq(0, 9) ],
+ PktR1 = inet_dns:encode(PktR0#dns_rec{ anlist = AnList1 }),
+ {ok,PktR1S,TS2} = inet_dns_tsig:sign(PktR1, TS1),
+ ok = gen_tcp:send(Sock, PktR1S),
+
+ AnList2 = [ Padding#dns_rr{
+ domain = io_lib:format(Format, [X]) } ||
+ X <- lists:seq(10, 19) ],
+ PktR2 = inet_dns:encode(PktR0#dns_rec{ anlist = AnList2 }),
+ {ok,PktR2S,TS3} = inet_dns_tsig:sign(PktR2, TS2),
+ ok = gen_tcp:send(Sock, PktR2S),
+
+ AnList3 = [ Padding#dns_rr{
+ domain = io_lib:format(Format, [X]) } ||
+ X <- lists:seq(20, 29) ] ++ [SOA],
+ PktR3 = inet_dns:encode(PktR0#dns_rec{ anlist = AnList3 }),
+ {ok,PktR3S,_TS} = inet_dns_tsig:sign(PktR3, TS3),
+ ok = gen_tcp:send(Sock, PktR3S).
+
+
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Compatibility tests. Call the inet_SUITE tests, but with
%% lookup = [file,dns] instead of [native]
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/knot_inc.conf b/lib/kernel/test/inet_res_SUITE_data/otptest/knot_inc.conf
index 50c9f0d977..91a48f62bf 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/knot_inc.conf
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/knot_inc.conf
@@ -1,10 +1,21 @@
+key:
+ - id: testkey.otptest
+ algorithm: hmac-sha256
+ # ded5ada3-07f2-42b9-84bf-82d30f6795ee
+ secret: ZGVkNWFkYTMtMDdmMi00MmI5LTg0YmYtODJkMzBmNjc5NWVl
+
acl:
- id: update_rule
address: 127.0.0.1
action: update
+acl:
+ - id: testkey_rule
+ key: testkey.otptest
+ action: transfer
+
zone:
- domain: otptest
- acl: [ update_rule ]
+ acl: [ update_rule, testkey_rule ]
- domain: 0.0.127.in-addr.arpa.
- domain: 0.0.0.0.f.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
diff --git a/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone b/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
index e94866a1f9..dc004896cb 100644
--- a/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
+++ b/lib/kernel/test/inet_res_SUITE_data/otptest/otptest.zone
@@ -61,3 +61,510 @@ minfo.resolve IN MINFO minfo-owner.resolve minfo-bounce.resolve
uri.resolve IN TYPE256 \# 21 000a 0003 (68747470 3a2f2f 65726c616e67 2e 6f7267)
;caa.resolve IN CAA 1 iodef "http://iodef.erlang.org"
caa.resolve IN TYPE257 \# 30 01 (05 696f646566) (68747470 3a2f2f 696f646566 2e 65726c616e67 2e 6f7267)
+
+; for testing TSIG we need a multi-message response so we use AXFR but need
+; to juice up the zone file to meet our needs, the following creates 3 messages
+;
+; N.B. knotd does not support $GENERATE so here we go...
+;
+;$GENERATE 0-599 ${0,3,d} $.padding TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+000.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+001.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+002.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+003.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+004.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+005.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+006.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+007.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+008.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+009.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+010.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+011.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+012.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+013.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+014.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+015.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+016.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+017.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+018.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+019.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+020.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+021.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+022.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+023.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+024.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+025.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+026.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+027.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+028.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+029.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+030.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+031.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+032.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+033.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+034.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+035.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+036.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+037.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+038.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+039.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+040.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+041.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+042.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+043.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+044.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+045.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+046.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+047.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+048.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+049.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+050.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+051.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+052.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+053.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+054.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+055.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+056.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+057.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+058.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+059.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+060.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+061.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+062.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+063.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+064.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+065.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+066.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+067.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+068.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+069.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+070.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+071.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+072.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+073.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+074.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+075.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+076.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+077.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+078.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+079.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+080.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+081.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+082.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+083.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+084.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+085.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+086.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+087.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+088.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+089.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+090.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+091.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+092.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+093.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+094.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+095.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+096.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+097.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+098.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+099.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+100.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+101.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+102.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+103.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+104.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+105.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+106.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+107.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+108.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+109.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+110.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+111.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+112.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+113.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+114.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+115.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+116.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+117.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+118.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+119.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+120.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+121.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+122.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+123.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+124.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+125.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+126.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+127.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+128.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+129.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+130.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+131.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+132.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+133.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+134.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+135.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+136.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+137.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+138.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+139.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+140.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+141.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+142.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+143.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+144.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+145.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+146.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+147.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+148.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+149.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+150.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+151.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+152.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+153.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+154.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+155.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+156.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+157.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+158.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+159.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+160.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+161.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+162.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+163.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+164.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+165.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+166.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+167.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+168.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+169.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+170.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+171.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+172.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+173.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+174.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+175.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+176.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+177.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+178.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+179.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+180.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+181.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+182.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+183.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+184.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+185.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+186.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+187.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+188.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+189.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+190.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+191.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+192.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+193.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+194.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+195.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+196.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+197.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+198.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+199.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+200.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+201.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+202.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+203.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+204.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+205.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+206.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+207.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+208.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+209.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+210.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+211.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+212.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+213.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+214.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+215.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+216.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+217.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+218.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+219.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+220.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+221.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+222.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+223.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+224.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+225.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+226.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+227.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+228.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+229.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+230.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+231.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+232.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+233.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+234.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+235.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+236.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+237.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+238.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+239.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+240.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+241.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+242.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+243.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+244.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+245.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+246.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+247.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+248.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+249.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+250.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+251.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+252.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+253.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+254.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+255.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+256.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+257.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+258.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+259.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+260.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+261.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+262.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+263.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+264.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+265.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+266.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+267.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+268.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+269.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+270.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+271.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+272.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+273.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+274.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+275.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+276.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+277.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+278.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+279.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+280.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+281.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+282.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+283.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+284.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+285.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+286.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+287.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+288.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+289.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+290.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+291.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+292.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+293.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+294.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+295.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+296.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+297.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+298.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+299.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+300.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+301.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+302.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+303.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+304.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+305.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+306.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+307.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+308.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+309.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+310.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+311.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+312.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+313.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+314.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+315.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+316.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+317.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+318.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+319.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+320.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+321.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+322.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+323.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+324.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+325.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+326.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+327.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+328.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+329.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+330.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+331.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+332.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+333.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+334.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+335.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+336.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+337.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+338.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+339.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+340.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+341.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+342.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+343.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+344.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+345.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+346.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+347.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+348.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+349.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+350.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+351.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+352.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+353.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+354.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+355.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+356.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+357.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+358.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+359.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+360.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+361.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+362.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+363.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+364.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+365.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+366.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+367.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+368.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+369.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+370.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+371.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+372.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+373.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+374.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+375.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+376.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+377.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+378.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+379.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+380.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+381.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+382.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+383.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+384.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+385.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+386.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+387.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+388.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+389.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+390.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+391.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+392.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+393.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+394.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+395.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+396.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+397.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+398.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+399.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+400.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+401.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+402.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+403.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+404.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+405.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+406.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+407.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+408.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+409.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+410.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+411.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+412.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+413.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+414.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+415.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+416.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+417.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+418.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+419.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+420.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+421.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+422.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+423.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+424.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+425.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+426.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+427.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+428.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+429.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+430.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+431.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+432.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+433.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+434.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+435.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+436.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+437.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+438.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+439.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+440.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+441.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+442.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+443.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+444.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+445.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+446.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+447.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+448.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+449.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+450.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+451.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+452.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+453.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+454.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+455.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+456.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+457.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+458.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+459.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+460.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+461.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+462.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+463.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+464.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+465.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+466.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+467.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+468.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+469.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+470.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+471.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+472.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+473.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+474.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+475.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+476.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+477.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+478.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+479.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+480.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+481.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+482.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+483.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+484.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+485.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+486.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+487.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+488.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+489.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+490.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+491.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+492.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+493.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+494.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+495.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+496.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+497.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+498.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+499.padding IN TXT "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
--
2.35.3