File Coverage

blib/lib/Metabrik/Network/Wlan.pm
Criterion Covered Total %
statement 9 137 6.5
branch 0 58 0.0
condition 0 27 0.0
subroutine 3 11 27.2
pod 1 7 14.2
total 13 240 5.4


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # network::wlan Brik
5             #
6             package Metabrik::Network::Wlan;
7 1     1   728 use strict;
  1         3  
  1         30  
8 1     1   5 use warnings;
  1         2  
  1         26  
9              
10 1     1   6 use base qw(Metabrik::Shell::Command Metabrik::System::Package);
  1         2  
  1         1592  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable wifi wlan wireless monitor) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             device => [ qw(device) ],
20             monitor => [ qw(device) ],
21             essid => [ qw(essid) ],
22             key => [ qw(key) ],
23             bitrate => [ qw(bitrate_mb|54MB|130MB) ],
24             _monitor_mode_started => [ ],
25             },
26             attributes_default => {
27             device => 'wlan0',
28             monitor => 'mon0',
29             },
30             commands => {
31             install => [ ], # Inherited
32             scan => [ qw(device|OPTIONAL) ],
33             set_bitrate => [ qw(bitrate|OPTIONAL device|OPTIONAL) ],
34             set_wepkey => [ qw(key|OPTIONAL device|OPTIONAL) ],
35             connect => [ qw(device|OPTIONAL essid|OPTIONAL) ],
36             start_monitor_mode => [ qw(device|OPTIONAL) ],
37             stop_monitor_mode => [ qw(monitor|OPTIONAL) ],
38             },
39             require_binaries => {
40             'sudo', => [ ],
41             'iwlist', => [ ],
42             'iwconfig', => [ ],
43             },
44             optional_binaries => {
45             'airmon-ng' => [ ],
46             },
47             need_packages => {
48             ubuntu => [ qw(aircrack-ng iw) ],
49             debian => [ qw(aircrack-ng iw) ],
50             kali => [ qw(aircrack-ng iw) ],
51             },
52             };
53             }
54              
55             sub scan {
56 0     0 0   my $self = shift;
57 0           my ($device) = @_;
58              
59 0   0       $device ||= $self->device;
60 0 0         $self->brik_help_run_undef_arg('scan', $device) or return;
61              
62 0           $self->log->verbose("scan: using device [$device]");
63              
64 0           my $cmd = "iwlist $device scan";
65              
66 0           my $result = $self->capture($cmd);
67              
68 0 0         if (@$result > 0) {
69 0           return $self->_list_ap($result);
70             }
71              
72 0           return $self->log->error("scan: no result");
73             }
74              
75             sub _list_ap {
76 0     0     my $self = shift;
77 0           my ($scan) = @_;
78              
79 0           my $ap_hash = {};
80              
81 0           my $cell = '';
82 0           my $address = '';
83 0           my $channel = '';
84 0           my $frequency = '';
85 0           my $essid = '';
86 0           my $encryption = '';
87 0           my $raw = [];
88 0           my $quality = '';
89 0           for my $line (@$scan) {
90 0           push @$raw, $line;
91              
92 0 0         if ($line =~ /^\s+Cell\s+(\d+).*Address:\s+(.*)$/) {
93             # We just hit a new Cell, we reset data.
94 0 0         if (length($cell)) {
95 0           $ap_hash->{"cell_$cell"} = {
96             cell => $cell,
97             address => $address,
98             essid => $essid,
99             encryption => $encryption,
100             raw => $raw,
101             quality => $quality,
102             };
103              
104 0           $cell = '';
105 0           $address = '';
106 0           $channel = '';
107 0           $frequency = '';
108 0           $essid = '';
109 0           $encryption = '';
110 0           $raw = [];
111 0           $quality = '';
112              
113             # We put back the current line.
114 0           push @$raw, $line;
115             }
116 0           $cell = $1;
117 0           $address = $2;
118 0           next;
119             }
120              
121 0 0         if ($line =~ /^\s+Channel:(\d+)/) {
122 0           $channel = $1;
123 0           next;
124             }
125              
126 0 0         if ($line =~ /^\s+Frequency:(\d+\.\d+)/) {
127 0           $frequency = $1;
128 0           next;
129             }
130              
131 0 0         if ($line =~ /^\s+Quality=(\d+)\/(\d+)/) {
132 0           $quality = sprintf("%.2f", 100 * $1 / $2);
133 0           next;
134             }
135              
136 0 0         if ($line =~ /^\s+Encryption key:(\S+)/) {
137 0           my $this = $1;
138 0 0         if ($this eq 'off') {
    0          
139 0           $encryption = 0;
140             }
141             elsif ($this eq 'on') {
142 0           $encryption = 1;
143             }
144             else {
145 0           $encryption = -1;
146             }
147             }
148              
149 0 0         if ($line =~ /^\s+ESSID:"(\S+)"/) {
150 0           $essid = $1;
151 0           $self->log->verbose("cell [$cell] address [$address] essid[$essid] encryption[$encryption] quality[$quality] channel[$channel] frequency[$frequency]");
152 0           next;
153             }
154              
155             }
156              
157 0           $ap_hash->{"cell_$cell"} = {
158             cell => $cell,
159             address => $address,
160             channel => $channel,
161             frequency => $frequency,
162             essid => $essid,
163             encryption => $encryption,
164             raw => $raw,
165             quality => $quality,
166             };
167              
168 0           return $ap_hash;
169             }
170              
171             sub connect {
172 0     0 0   my $self = shift;
173 0           my ($device, $essid) = @_;
174              
175 0   0       $device ||= $self->device;
176 0   0       $essid ||= $self->essid;
177 0 0         $self->brik_help_run_undef_arg('connect', $device) or return;
178 0 0         $self->brik_help_run_undef_arg('connect', $essid) or return;
179              
180 0           my $cmd = "sudo iwconfig $device essid $essid";
181              
182 0           $self->capture_stderr(1);
183 0 0         my $r = $self->capture($cmd) or return;
184              
185 0           $self->log->verbose("connect: $r");
186              
187 0 0         $self->set_bitrate or return;
188              
189             # For WEP, we can use:
190             # "iwconfig $device key $key"
191              
192 0           return $r;
193             }
194              
195             sub set_bitrate {
196 0     0 0   my $self = shift;
197 0           my ($bitrate, $device) = @_;
198              
199 0   0       $bitrate ||= $self->bitrate;
200 0   0       $device ||= $self->device;
201 0 0         $self->brik_help_run_undef_arg('set_bitrate', $bitrate) or return;
202 0 0         $self->brik_help_run_undef_arg('set_bitrate', $device) or return;
203              
204 0           my $cmd = "sudo iwconfig $device rate $bitrate";
205              
206 0           $self->capture_stderr(1);
207              
208 0           return $self->capture($cmd);
209             }
210              
211             sub set_wepkey {
212 0     0 0   my $self = shift;
213 0           my ($key, $device) = @_;
214              
215 0   0       $key ||= $self->key;
216 0   0       $device ||= $self->device;
217 0 0         $self->brik_help_run_undef_arg('set_wepkey', $key) or return;
218 0 0         $self->brik_help_run_undef_arg('set_wepkey', $device) or return;
219              
220 0           my $cmd = "sudo iwconfig $device key $key";
221              
222 0           $self->capture_stderr(1);
223              
224 0           return $self->capture($cmd);
225             }
226              
227             sub start_monitor_mode {
228 0     0 0   my $self = shift;
229 0           my ($device) = @_;
230              
231 0   0       $device ||= $self->device;
232 0 0         $self->brik_help_run_undef_arg('start_monitor_mode', $device) or return;
233              
234             # airmon-ng is optional, so we check here.
235 0           my $found = $self->brik_has_binary('airmon-ng');
236 0 0         if (! $found) {
237 0           return $self->log->error("start_monitor_mode: you have to install aircrack-ng package");
238             }
239              
240 0           my $cmd = "sudo airmon-ng start $device";
241              
242 0           $self->capture_stderr(1);
243              
244 0           my $r = $self->capture($cmd);
245              
246 0 0         if (defined($r)) {
247 0           my $monitor = '';
248 0           for my $line (@$r) {
249 0 0         if ($line =~ /monitor mode enabled on (\S+)\)/) {
250 0           $monitor = $1;
251 0           last;
252             }
253             }
254              
255 0 0         if (! length($monitor)) {
256 0           return $self->log->error("start_monitor_mode: cannot start monitor mode");
257             }
258              
259 0 0         if ($monitor !~ /^[a-z]+(?:\d+)?$/) {
260 0           return $self->log->error("start_monitor_mode: cannot start monitor mode with monitor [$monitor]");
261             }
262              
263 0           $self->monitor($monitor);
264 0           $self->_monitor_mode_started(1);
265             }
266              
267 0           return $self->monitor;
268             }
269              
270             sub stop_monitor_mode {
271 0     0 0   my $self = shift;
272 0           my ($monitor) = @_;
273              
274 0   0       $monitor ||= $self->monitor;
275 0           my $started = $self->_monitor_mode_started;
276 0 0         $self->brik_help_run_undef_arg('start_monitor_mode', $started) or return;
277 0 0         $self->brik_help_run_undef_arg('start_monitor_mode', $monitor) or return;
278              
279             # airmon-ng is optional, so we check here.
280 0           my $found = $self->brik_has_binary('airmon-ng');
281 0 0         if (! $found) {
282 0           return $self->log->error("stop_monitor_mode: you have to install aircrack-ng package");
283             }
284              
285 0           my $cmd = "sudo airmon-ng stop $monitor";
286              
287 0           $self->capture_stderr(1);
288              
289 0           my $r = $self->capture($cmd);
290              
291 0 0         if (defined($r)) {
292 0           $self->_monitor_mode_started(0);
293             }
294              
295 0           return $r;
296             }
297              
298             1;
299              
300             __END__