File: bin2packet

package info (click to toggle)
libnet-radius-perl 2.103%2Bdfsg-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 1,276 kB
  • sloc: perl: 4,561; tcl: 33; makefile: 2
file content (320 lines) | stat: -rwxr-xr-x 7,968 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#!/usr/bin/perl

no utf8;
use strict;
use warnings;

our $VERSION = do { sprintf "%0.03f", (q$Revision: 93 $ =~ /\d+/g) };

use IO::File;
use IO::Prompt;
use Pod::Usage;
use Data::Dumper;
use Getopt::Long;
use Net::Radius::Packet;
use Net::Radius::Dictionary;

use UNIVERSAL qw/isa/;

my %opt;
GetOptions(\%opt, qw/
	   dictionary=s@
	   authenticator=s
	   code=s
	   description=s
	   dont-embed-dict
	   dump
	   help
	   identifier=i
	   noprompt
	   output=s
	   secret=s
	   slots=i
	   /);

my %data = ();

pod2usage(verbose => 2, exitval => 0) 
    if $opt{help};

pod2usage(verbose => 1, exitval => 1,
	  message => 'Missing dictionary specification')
    unless $opt{dictionary} and @{$opt{dictionary}};

pod2usage(verbose => 1, exitval => 1,
	  message => 'Missing output file specification')
    unless $opt{output};

my $output = $opt{output} . ".p";

pod2usage(verbose => 1, exitval => 1,
	  message => "Won't clobber existing output file $output")
    if -f $output;

# Format general warnings
local $SIG{__WARN__} = sub { warn "bin2packet: ", @_ };

# Further processing will need us to read and parse a dictioary file -
# Let's do this.

my $d = new Net::Radius::Dictionary;

foreach (@{$opt{dictionary}})
{
    die "Dictionary $_ unreadable: ", ($!||'Check permissions'), "\n" 
	unless -r $_;
    $d->readfile($_);
}

$data{dictionary} = $opt{'dont-embed-dict'} ? undef : $d;
$data{opts} = \%opt; 

# Attempt to parse the packet, to auto-guess information and provide a
# packet dump

my $file = shift @ARGV;

pod2usage(verbose => 1, exitval => 1,
	  message => "Must specify a packet dump file to process")
    unless $file;

my $fh = new IO::File $file, "r";

pod2usage(verbose => 1, exitval => 1,
	  message => "Failed to read dump file $file: $!")
    unless $fh;

my $packet;

do {
    local $/ = undef;
    $data{packet} = <$fh>;
};

close $fh;

warn length($data{packet}), " octets read from file $file\n";

my $p;

eval 
{ 
    local $SIG{__WARN__} = sub {warn "bin2packet (during decode): ", @_ }; 
    $p = new Net::Radius::Packet $d, $data{packet}; 
};

warn "(Decoding error) $_\n" for split(/\n/, $@);

if ($p and isa($p, 'Net::Radius::Packet'))
{
    warn "Packet decoded\n";

    unless (defined $opt{authenticator})
    {
	my $auth = $p->authenticator;
	if (length($auth) == 16)
	{
	    warn "authenticator taken from the packet\n";
	    $opt{authenticator} = $auth;
	}
	else
	{
	    warn "authenticator looks weird - ignoring\n";
	}
    }

    unless (defined $opt{identifier})
    {
	my $id = $p->identifier;
	warn "identifier set to $id from the packet\n";
	$opt{identifier} = $id;
    }

    unless (defined $opt{slots})
    {
	my $id = $p->attr_slots;
	warn "slots set to $id from the packet\n";
	$opt{slots} = $id;
    }
}
else
{
    warn "Failed to decode packet\n";
}

if ($opt{dump})
{
    print $p->dump;
    exit 0;
}

# Add default (unknown) values and build the base structure where the
# information is to be stored

foreach (qw/secret authenticator identifier description slots/)
{
    next if defined $opt{$_};
    unless ($opt{noprompt})
    {
	$opt{$_} = prompt("Enter packet $_ (if known): ", -tty,
			  ($_ eq 'secret' ? (-echo => '*') : ()));
	# Simplify the stored object by removing the reference to
	# IO::Prompt::ReturnVal
	$opt{$_} = "$opt{$_}";
    }
    $opt{$_} = undef unless defined $opt{$_};
}
continue
{
    $data{$_} = $opt{$_};
}

die "Failed to create output file $output: $!\n"
    unless $fh = new IO::File $output, "w+";

die "Failed storing contents of file $output: $!\n"
    unless print $fh "#!/usr/bin/perl\n\n" .
    "no utf8;\n\n# Net::Radius test input\n" . '# Made with $Id: bin2packet 93 2009-09-23 14:38:39Z lem $' 
    . "\n\n" . Data::Dumper->Dump([\%data]);

die "Failed to close output file $output: $!\n"
    unless close $fh;

warn "Test input $output succesfully created\n";
exit 0;

__END__

=head1 NAME

bin2packet - Convert a RADIUS packet payload into a useable test point

=head1 SYNOPSIS

    bin2packet --dictionary dictfile [--authenticator auth-string]
    [--code code] [--description packet-desc] [--dont-embed-dict]
    [--dump] [--help] [--identifier id] [--noprompt] [--output file]
    [--secret secret] [--slots number] dump-file...

=head1 DESCRIPTION

This tool is used to convert the payload of a RADIUS packet stored in
B<dump-file> into a "test input". This test input can then be used by
the test harness included in the Net::Radius::Packet(3) distribution
as part of the regression tests.

The following options are supported (Options can be shortened - See
Getopt::Long(3)):

=over

=item B<--dictionary dictfile...>

Specifies one or more dictionary files to use for decoding the
supplied packet. Those dictionaries may be required for derived tests
to work properly (ie, match the expected attribute names and/or
values).

A serialized dictionary is appended to the test input.

This argument is mandatory.

=item B<--authenticator auth-string>

Specifies the RADIUS packet authenticator. If the provided
packet dump can be decoded by Net::Radius::Packet, this value will be
supplied automatically. If the guess is wrong, you must use this
option to provide a correct value.

=item B<--code code>

The RADIUS packet code. If the provided packet dump can be decoded by
Net::Radius::Packet, this value will be supplied automatically. If the
guess is wrong, you must use this option to provide a correct value.

=item B<--description packet-desc>

A (hopefully) informative description of this packet. The most
relevant information items that should be present is the name/version
of the device that generated the packet, as well as a concise
reference to where this packet belongs (ie, simple user
authentication).

=item B<--dont-embed-dict>

Causes the resulting test input to not embed the
Net::Radius::Dictionary(3) object used to contain the dictionary
data. This can be used when only dictionaries found in the
distribution are used to process the packet.

=item B<--dump>

Dump the decoded packet and exit without further actions.

=item B<--help>

Shows this documentation, then exits.

=item B<--identifier id>

Specifies the RADIUS packet identifier, if known. If the provided
packet dump can be decoded by Net::Radius::Packet, this value will be
supplied automatically. If the guess is wrong, you must use this
option to provide a correct value.

=item B<--noprompt>

All the packet information items available in the command-line will be
prompted if not specified. This option causes non-supplied options to
remain undefined, which may prevent certain tests over the packet.

=item B<--output file>

Name of the file where this test input will be stored. The B<.p>
extension will be automatically added.

=item B<--secret secret>

Specify the RADIUS secret to use for decoding the packet. If not
specified, it will be prompted depending on the B<--noprompt> option.

=item B<--slots number>

Specify the number of attribute slots (ie, attribute-value tuples)
stored in the RADIUS packet. If the provided packet dump can be
decoded by Net::Radius::Packet, this value will be supplied
automatically. If the guess is wrong, you must use this option to
provide a correct value.

=back

=head1 HISTORY

    $Log$
    Revision 1.2  2007/01/14 18:51:42  lem
    When Dump()ing and eval()ing back the packet, IO::Prompt::ReturnVal
    may not be within reach of the test script (different machine,
    etc). Make sure we drop this magic when we generate the test input.

    Revision 1.1  2007/01/09 17:55:10  lem
    First release of bin2packet added


=head1 LICENSE AND WARRANTY

This code and all accompanying software comes with NO WARRANTY. You
use it at your own risk.

This code and all accompanying software can be used freely under the
same terms as Perl version 5.8.6 itself.

=head1 AUTHOR

Luis E. Muñoz E<lt>luismunoz@cpan.orgE<gt>

=head1 SEE ALSO

perl(1), Getopt::Long(3), Net::Radius::Packet(3),
Net::Radius::Dictionary(3).

=cut