File Coverage

lib/SMB/v2/Command/Negotiate.pm
Criterion Covered Total %
statement 12 67 17.9
branch 0 14 0.0
condition 0 9 0.0
subroutine 4 10 40.0
pod 0 6 0.0
total 16 106 15.0


line stmt bran cond sub pod time code
1             # SMB Perl library, Copyright (C) 2014-2018 Mikhael Goikhman, migo@cpan.org
2             #
3             # This program is free software: you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation, either version 3 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16             package SMB::v2::Command::Negotiate;
17              
18 1     1   6 use strict;
  1         2  
  1         24  
19 1     1   4 use warnings;
  1         1  
  1         21  
20              
21 1     1   4 use parent 'SMB::v2::Command';
  1         1  
  1         5  
22              
23 1     1   37 use SMB::Time;
  1         2  
  1         646  
24              
25             sub new_from_v1 ($$) {
26 0     0 0   my $class = shift;
27 0           my $command1 = shift;
28              
29 0           my $header1 = $command1->header;
30              
31 0 0         my $flags = $header1->{flags} & SMB::v1::Header::FLAGS_RESPONSE ? SMB::v2::Header::FLAGS_RESPONSE : 0;
32             my $security_mode =
33             ($header1->{flags2} & SMB::v1::Header::FLAGS2_SECURITY_SIGNATURE ? 1 : 0) |
34 0 0         ($header1->{flags2} & SMB::v1::Header::FLAGS2_SECURITY_SIGNATURE_REQUIRED ? 2 : 0);
    0          
35              
36 0           my $header = SMB::v2::Header->new(
37             code => 0,
38             mid => 0,
39             flags => $flags,
40             status => $command1->status,
41             );
42              
43 0           my $self = $class->SUPER::new($header);
44              
45 0           $self->set(
46             security_mode => $security_mode,
47             dialects => [ 0x0202, 0x02ff ],
48             );
49              
50 0           return $self;
51             }
52              
53             sub get_system_boot_time () {
54 0   0 0 0   chomp(my $boot_str = `uptime -s 2>/dev/null` || '');
55 0           chomp(my $boot_time = `date +%s -d "$boot_str" 2>/dev/null`);
56              
57 0 0         return $boot_time =~ /^(\d{9,10})$/ ? $1 : time;
58             }
59              
60             sub init ($) {
61 0     0 0   $_[0]->set(
62             dialects => [ 0x0202, 0x0210, 0x02ff ],
63             dialect => 0x0210,
64             security_mode => 0,
65             capabilities => 0x7,
66             guid => "\5" x 16,
67             max_transact_size => 1 << 20,
68             max_read_size => 1 << 16,
69             max_write_size => 1 << 16,
70             current_time => 0,
71             boot_time => 0,
72             security_buffer => undef,
73             )
74             }
75              
76             sub parse ($$%) {
77 0     0 0   my $self = shift;
78 0           my $parser = shift;
79              
80 0 0         if ($self->is_response) {
81 0           $self->security_mode($parser->uint16);
82 0           $self->dialect($parser->uint16);
83 0           $parser->uint16; # reserved
84 0           $self->guid($parser->bytes(16));
85 0           $self->capabilities($parser->uint32);
86 0           $self->max_transact_size($parser->uint32);
87 0           $self->max_read_size($parser->uint32);
88 0           $self->max_write_size($parser->uint32);
89 0           $self->current_time($parser->uint64);
90 0           $self->boot_time($parser->uint64);
91 0           my $offset = $parser->uint16;
92 0           my $length = $parser->uint16;
93 0           $parser->uint32; # reserved2
94 0           $self->security_buffer($parser->bytes($length));
95             } else {
96 0           my $num_dialects = $parser->uint16;
97 0           $self->security_mode($parser->uint16);
98 0           $parser->uint16; # reserved
99 0           $self->capabilities($parser->uint32);
100 0           $self->guid($parser->bytes(16));
101 0           $self->boot_time($parser->uint64);
102 0           $self->dialects([ map { $parser->uint16 } 1 .. $num_dialects ]);
  0            
103             }
104              
105 0           return $self;
106             }
107              
108             sub pack ($$) {
109 0     0 0   my $self = shift;
110 0           my $packer = shift;
111              
112 0           $self->boot_time(to_nttime(get_system_boot_time()));
113              
114 0 0         if ($self->is_response) {
115 0   0       my $security_buffer = $self->security_buffer // die 'No security_buffer';
116 0           $self->current_time(to_nttime(time()));
117              
118 0   0       $packer
119             ->uint16($self->security_mode)
120             ->uint16($self->dialects->[1] || $self->dialect)
121             ->uint16(0) # reserved
122             ->bytes ($self->guid)
123             ->uint32($self->capabilities)
124             ->uint32($self->max_transact_size)
125             ->uint32($self->max_read_size)
126             ->uint32($self->max_write_size)
127             ->uint64($self->current_time)
128             ->uint64($self->boot_time)
129             ->uint16($packer->diff('smb-header') + 8)
130             ->uint16(length $security_buffer)
131             ->uint32(0) # reserved2
132             ->bytes ($security_buffer)
133             ;
134             } else {
135 0           my $dialects = $self->dialects;
136 0           $packer
137             ->uint16(scalar @$dialects)
138             ->uint16($self->security_mode)
139             ->uint16(0) # reserved
140             ->uint32($self->capabilities)
141             ->bytes ($self->guid)
142             ->uint64($self->boot_time)
143             ;
144 0           $packer->uint16($_) for @$dialects;
145             }
146             }
147              
148             sub supports_smb_dialect ($$) {
149 0     0 0   my $self = shift;
150 0   0       my $dialect0 = shift || die;
151              
152 0           for my $dialect (@{$self->dialects}) {
  0            
153 0 0         return 1 if $dialect > $dialect0;
154             }
155              
156 0           return 0;
157             }
158              
159             1;