tails-restricted-network-detector 2.34 KB
Newer Older
1 2 3 4 5 6 7 8 9
#!/usr/bin/env perl

use strict;
use warnings;

#man{{{

=head1 NAME

10
tails-restricted-network-detector
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

=head1 VERSION

Version X.XX

=head1 AUTHOR

Tails dev team <tails@boum.org>
See https://tails.boum.org/.

=cut

#}}}

use File::Tail;
use Parse::Syslog;
27
use IPC::System::Simple qw(runx);
28
use Locale::gettext;
Tails developers's avatar
Tails developers committed
29 30
use I18N::Langinfo qw{langinfo CODESET};
use Encode qw{decode find_encoding};
31 32 33 34 35 36
use POSIX;

setlocale(LC_MESSAGES, "");
textdomain("tails");

sub notify_maybe_blocked {
Tails developers's avatar
Tails developers committed
37 38 39
    my $encoding = find_encoding(langinfo(CODESET()));
    my $summary  = $encoding->decode(gettext('Network connection blocked?'));
    my $body     = $encoding->decode(gettext(
40 41
        'It looks like you are blocked from the network. This may be ' .
        'related to the MAC spoofing feature. For more information, see the ' .
42 43 44
        '<a href=\"file:///usr/share/doc/tails/website/doc/first_steps/' .
        'startup_options/mac_spoofing.en.html#blocked\">MAC spoofing ' .
        'documentation</a>.'));
45 46 47
    # We can't use Desktop::Notify since this script is supposed to be run
    # as root (for access to syslog), started in an env without DESKTOP etc,
    # which also causes issues with opening links in the text body.
Tails developers's avatar
Tails developers committed
48
    # All this works fine with tails-notify-user.
49
    runx('/usr/local/sbin/tails-notify-user', ($summary, $body, '30000'));
50 51
}

52
my %state;
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
my $syslog = File::Tail->new(name => "/var/log/syslog",
                             maxinterval => 1,
                             interval => 1);
my $parser = Parse::Syslog->new($syslog, allow_future => 1);
while(my $sl = $parser->next) {
    next if !($sl->{program} eq "NetworkManager");
    my $text = $sl->{text};
    if ($text =~ /Activation \(([^)]+)\) starting connection/) {
        # The beginning of *all* (not only wireless) new
        # connections. We drop any previous state so it won't
        # interfere.
        $state{$1} = undef;
    } elsif ($text =~ /\(([^)]+)\): supplicant connection state:.*-> (.*)$/) {
        # Wireless connection state transition.
        $state{$1} = $2;
    } elsif ($text =~ /Activation \(([^)]+)\/[^)]*\): association took too long/) {
        # Wireless connection failure. If it happens during
        # "associating" it *may* indicate that the AP is blocking the
        # MAC address in use.
        if ($state{$1} eq "associating") {
            notify_maybe_blocked();
        }
    }
}