File: nnrpd_access.pl.in

package info (click to toggle)
inn2 2.5.4-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 11,720 kB
  • ctags: 8,983
  • sloc: ansic: 92,499; sh: 13,509; perl: 12,921; makefile: 2,985; yacc: 842; python: 342; lex: 255
file content (121 lines) | stat: -rw-r--r-- 4,212 bytes parent folder | download | duplicates (6)
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
#! /usr/bin/perl -w
# fixscript will replace this line with code to load INN::Config

##
##  Sample code for the nnrpd Perl access hooks.

##  This file is loaded when a perl_access: parameter is reached in
##  readers.conf.  If it defines a sub named access, which will be
##  called during processing of a perl_access: parameter. Attributes
##  about the connection are passed to the program in the %attributes
##  global variable.  It should return a hash containing
##  parameter-value pairs for the access group. If there is a problem,
##  nnrpd will die and syslog the exact error.

##  The default behavior of the following code is to look for nnrp.access
##  in INN's configuration file directory and to attempt to implement about
##  the same host-based access control as the previous nnrp.access code in
##  earlier versions of INN.  This may be useful for backward compatibility.

##  This file cannot be run as a standalone script, although it would be
##  worthwhile to add some code so that it could so that one could test the
##  results of various authentication and connection queries from the
##  command line.  The #! line at the top is just so that fixscript will
##  work.

# This function is called when perl_access: is reached in readers.conf.
# For details on all the information passed to it, see
# ~news/doc/hook-perl.
sub access {
   &loadnnrp($INN::Config::newsetc . '/nnrp.access');
   return &checkhost($attributes{hostname}, $attributes{ipaddress});
}

# Called at startup, this loads the nnrp.access file and converts it into a
# convenient internal format for later queries.
sub loadnnrp {
    my $file = shift;
    my ($block, $perm, $user, $pass);

    open (ACCESS, $file) or die "Could not open $file: $!\n";
    local $_;
    while (<ACCESS>) {
        my %tmp;

        chomp;
        s/\#.*//;
        ($block, $perm, $user, $pass, $tmp{groups}) = split /:/;
        next unless (defined $tmp{groups});

        # We don't support username/password entries, so be safe.
        next if ($user || $pass);

        # Change the wildmat pattern to a regex (this isn't thorough, as
        # some ranges won't be converted properly, but it should be good
        # enough for this purpose).
        if ($block !~ m%^(?:\d+\.){3}\d+/\d+$%) {
            $block =~ s/\./\\./g;
            $block =~ s/\?/./g;
            $block =~ s/\*/.*/g;
        }
        $tmp{block} = $block;

        $tmp{canread} = ($perm =~ /r/i);
        $tmp{canpost} = ($perm =~ /p/i);

        unshift(@hosts, { %tmp });
    }
    close ACCESS;
}

# Given the hostname and IP address of a connecting host, use our @hosts
# array constructed from nnrp.access and see what permissions that host has.
sub checkhost {
    my ($host, $ip) = @_;
    my %return_hash;
    my $key;
    for $key (@hosts) {
        my ($read, $post) = ($key->{canread}, $key->{canpost});

        # First check for CIDR-style blocks.
        if ($key->{block} =~ m%^(\d+\.\d+\.\d+\.\d+)/(\d+)$%) {
            my $block = unpack('N', pack('C4', split(/\./, $1)));
            my $mask = (0xffffffff << (32 - $2)) & 0xffffffff;
            $block = $block & $mask;
            my $packedip = unpack('N', pack('C4', split(/\./, $ip)));
            if (($packedip & $mask) == $block) {
                if ($read) {
                    $return_hash{"read"} = $key->{groups};
                }
                if ($post) {
                    $return_hash{"post"} = $key->{groups};
                }
                return %return_hash;
            }
        }

        if ($ip =~ /^$key->{block}$/) {
            if ($read) {
                $return_hash{"read"} = $key->{groups};
            }
            if ($post) {
                $return_hash{"post"} = $key->{groups};
            }
            return %return_hash;
        }

        if ($host =~ /^$key->{block}$/) {
            if ($read) {
                $return_hash{"read"} = $key->{groups};
            }
            if ($post) {
                $return_hash{"post"} = $key->{groups};
            }
            return %return_hash;
        }
    }

    # If we fell through to here, nothing matched, so we should deny
    # permissions.
    return %return_hash;
}