View | Details | Raw Unified | Return to bug 28657
Collapse All | Expand All

(-)a/C4/Auth.pm (-21 / +30 lines)
Lines 1197-1212 sub checkauth { Link Here
1197
1197
1198
                        # we have to check they are coming from the right ip range
1198
                        # we have to check they are coming from the right ip range
1199
                        my $domain = $branches->{$branchcode}->{'branchip'};
1199
                        my $domain = $branches->{$branchcode}->{'branchip'};
1200
                        $domain =~ s|\.\*||g;
1200
                        next unless ($domain);
1201
                        if ( $ip !~ /^$domain/ ) {
1201
                        if ( !in_iprange($domain) ) {
1202
                            $loggedin = 0;
1202
                            $loggedin = 0;
1203
                            $cookie = $cookie_mgr->replace_in_list( $cookie, $query->cookie(
1203
                            $cookie   = $cookie_mgr->replace_in_list(
1204
                                -name     => 'CGISESSID',
1204
                                $cookie,
1205
                                -value    => '',
1205
                                $query->cookie(
1206
                                -HttpOnly => 1,
1206
                                    -name     => 'CGISESSID',
1207
                                -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
1207
                                    -value    => '',
1208
                                -sameSite => 'Lax',
1208
                                    -HttpOnly => 1,
1209
                            ));
1209
                                    -secure => ( C4::Context->https_enabled() ? 1 : 0 ),
1210
                                    -sameSite => 'Lax',
1211
                                )
1212
                            );
1210
                            $info{'wrongip'} = 1;
1213
                            $info{'wrongip'} = 1;
1211
                        }
1214
                        }
1212
                    }
1215
                    }
Lines 1215-1225 sub checkauth { Link Here
1215
1218
1216
                        #     now we work with the treatment of ip
1219
                        #     now we work with the treatment of ip
1217
                        my $domain = $branches->{$br}->{'branchip'};
1220
                        my $domain = $branches->{$br}->{'branchip'};
1218
                        if ( $domain && $ip =~ /^$domain/ ) {
1221
                        next unless ($domain);
1222
                        if ( in_iprange($domain) ) {
1219
                            $branchcode = $branches->{$br}->{'branchcode'};
1223
                            $branchcode = $branches->{$br}->{'branchcode'};
1220
1224
1221
                            # new op dev : add the branchname to the cookie
1225
                            # new op dev : add the branchname to the cookie
1222
                            $branchname    = $branches->{$br}->{'branchname'};
1226
                            $branchname = $branches->{$br}->{'branchname'};
1223
                        }
1227
                        }
1224
                    }
1228
                    }
1225
1229
Lines 1651-1668 sub check_api_auth { Link Here
1651
                if ( $query->param('branch') ) {
1655
                if ( $query->param('branch') ) {
1652
                    $branchcode = $query->param('branch');
1656
                    $branchcode = $query->param('branch');
1653
                    my $library = Koha::Libraries->find($branchcode);
1657
                    my $library = Koha::Libraries->find($branchcode);
1654
                    $branchname = $library? $library->branchname: '';
1658
                    $branchname = $library ? $library->branchname: '';
1655
                }
1659
                }
1656
                my $branches = { map { $_->branchcode => $_->unblessed } Koha::Libraries->search->as_list };
1660
                my $branches = { map { $_->branchcode => $_->unblessed } Koha::Libraries->search->as_list };
1657
                foreach my $br ( keys %$branches ) {
1661
                foreach my $br ( keys %$branches ) {
1658
1662
1659
                    #     now we work with the treatment of ip
1663
                    #     now we work with the treatment of ip
1660
                    my $domain = $branches->{$br}->{'branchip'};
1664
                    my $domain = $branches->{$br}->{'branchip'};
1661
                    if ( $domain && $ip =~ /^$domain/ ) {
1665
                    next unless ($domain);
1666
                    if ( in_iprange($domain) ) {
1662
                        $branchcode = $branches->{$br}->{'branchcode'};
1667
                        $branchcode = $branches->{$br}->{'branchcode'};
1663
1668
1664
                        # new op dev : add the branchname to the cookie
1669
                        # new op dev : add the branchname to the cookie
1665
                        $branchname    = $branches->{$br}->{'branchname'};
1670
                        $branchname = $branches->{$br}->{'branchname'};
1666
                    }
1671
                    }
1667
                }
1672
                }
1668
                $session->param( 'number',       $borrowernumber );
1673
                $session->param( 'number',       $borrowernumber );
Lines 2315-2328 Returns 1 if the remote address is in the provided iprange, or 0 otherwise. Link Here
2315
2320
2316
sub in_iprange {
2321
sub in_iprange {
2317
    my ($iprange) = @_;
2322
    my ($iprange) = @_;
2318
    my $result = 1;
2323
    return 1 unless $iprange;
2319
    my @allowedipranges = $iprange ? split(' ', $iprange) : ();
2324
    my $result = 0;
2320
    if (scalar @allowedipranges > 0) {
2325
2326
    my @allowedipranges = $iprange ? split( ' ', $iprange ) : ();
2327
    if (@allowedipranges) {
2321
        my @rangelist;
2328
        my @rangelist;
2322
        eval { @rangelist = Net::CIDR::range2cidr(@allowedipranges); }; return 0 if $@;
2329
        eval { @rangelist = Net::CIDR::range2cidr(@allowedipranges); };
2323
        eval { $result = Net::CIDR::cidrlookup($ENV{'REMOTE_ADDR'}, @rangelist) } || Koha::Logger->get->warn('cidrlookup failed for ' . join(' ',@rangelist) );
2330
        return 0 if $@;
2324
     }
2331
        eval { $result = Net::CIDR::cidrlookup( $ENV{'REMOTE_ADDR'}, @rangelist ) }
2325
     return $result ? 1 : 0;
2332
            || Koha::Logger->get->warn( 'cidrlookup failed for ' . join( ' ', @rangelist ) );
2333
    }
2334
    return $result ? 1 : 0;
2326
}
2335
}
2327
2336
2328
sub getborrowernumber {
2337
sub getborrowernumber {
(-)a/Koha/Library.pm (+6 lines)
Lines 58-63 sub store { Link Here
58
        $flush = 1 if ( $self_from_storage->branchname ne $self->branchname );
58
        $flush = 1 if ( $self_from_storage->branchname ne $self->branchname );
59
    }
59
    }
60
60
61
    if ( $self->branchip =~ /\*/ ) {
62
        my $branchip = $self->branchip;
63
        $branchip =~ s/\*//g;
64
        $branchip =~ s/\.{2,}/./g;
65
        $self->branchip( $branchip );
66
    }
61
    $self = $self->SUPER::store;
67
    $self = $self->SUPER::store;
62
68
63
    if ($flush) {
69
    if ($flush) {
(-)a/installer/data/mysql/atomicupdate/bug_28657.pl (+26 lines)
Line 0 Link Here
1
use Modern::Perl;
2
3
return {
4
    bug_number  => "28657",
5
    description => "expand branches.branchip to allow for multiple ip ranges and remove '*'",
6
    up          => sub {
7
        my ($args) = @_;
8
        my ( $dbh, $out ) = @$args{qw(dbh out)};
9
10
        $dbh->do(
11
            q{ALTER TABLE `branches` MODIFY `branchip` mediumtext DEFAULT NULL COMMENT 'the IP address(s) for your library or branch'}
12
        );
13
        say $out "Modify column 'branches.branchip' to mediumtext";
14
15
        my $sth_select = $dbh->prepare(q{SELECT branchip,branchcode FROM branches WHERE branchip like '%*%'});
16
        my $sth_update = $dbh->prepare(q{UPDATE branches SET branchip = ? WHERE branchcode = ?});
17
        $sth_select->execute;
18
        my $results = $sth_select->fetchall_arrayref( {} );
19
        foreach (@$results) {
20
            $_->{'branchip'} =~ s/\*//g;
21
            $_->{'branchip'} =~ s/\.{2,}/./g;
22
            $sth_update->execute( $_->{'branchip'}, $_->{'branchcode'} );
23
        }
24
        say $out "Update column 'branches.branchip' to remove '*'";
25
    },
26
};
(-)a/installer/data/mysql/kohastructure.sql (-1 / +1 lines)
Lines 1603-1609 CREATE TABLE `branches` ( Link Here
1603
  `branchreturnpath` longtext DEFAULT NULL COMMENT 'the email to be used as Return-Path',
1603
  `branchreturnpath` longtext DEFAULT NULL COMMENT 'the email to be used as Return-Path',
1604
  `branchurl` longtext DEFAULT NULL COMMENT 'the URL for your library or branch''s website',
1604
  `branchurl` longtext DEFAULT NULL COMMENT 'the URL for your library or branch''s website',
1605
  `issuing` tinyint(4) DEFAULT NULL COMMENT 'unused in Koha',
1605
  `issuing` tinyint(4) DEFAULT NULL COMMENT 'unused in Koha',
1606
  `branchip` varchar(15) DEFAULT NULL COMMENT 'the IP address for your library or branch',
1606
  `branchip` mediumtext DEFAULT NULL COMMENT 'the IP address(s) for your library or branch',
1607
  `branchnotes` longtext DEFAULT NULL COMMENT 'notes related to your library or branch',
1607
  `branchnotes` longtext DEFAULT NULL COMMENT 'notes related to your library or branch',
1608
  `geolocation` varchar(255) DEFAULT NULL COMMENT 'geolocation of your library',
1608
  `geolocation` varchar(255) DEFAULT NULL COMMENT 'geolocation of your library',
1609
  `marcorgcode` varchar(16) DEFAULT NULL COMMENT 'MARC Organization Code, see http://www.loc.gov/marc/organizations/orgshome.html, when empty defaults to syspref MARCOrgCode',
1609
  `marcorgcode` varchar(16) DEFAULT NULL COMMENT 'MARC Organization Code, see http://www.loc.gov/marc/organizations/orgshome.html, when empty defaults to syspref MARCOrgCode',
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt (-2 / +2 lines)
Lines 246-253 Link Here
246
                </li>
246
                </li>
247
                <li>
247
                <li>
248
                    <label for="branchip">IP: </label>
248
                    <label for="branchip">IP: </label>
249
                    <input type="text" name="branchip" id="branchip"  size="15" maxlength="15" value="[% library.branchip | html %]" />
249
                    <input type="text" name="branchip" id="branchip"  size="60" value="[% library.branchip | html %]" />
250
                    <div class="hint">Can be entered as a single IP, or a subnet such as 192.168.1.*</div>
250
                    <div class="hint">Can be entered as a single IP, an IP range such as 192.168.1. or 192.168.1.10-192.168.1.50 or 192.168.1.0/24, or multiple space separated IP addresses or ranges.</div>
251
                </li>
251
                </li>
252
                <li>
252
                <li>
253
                    <label for="marcorgcode">MARC organization code</label>
253
                    <label for="marcorgcode">MARC organization code</label>
(-)a/t/Auth.t (-14 / +15 lines)
Lines 16-37 Link Here
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
use Test::More tests => 12;
19
use Test::More tests => 14;
20
use Test::Warn;
20
use Test::Warn;
21
21
22
use C4::Auth qw( in_iprange );
22
use C4::Auth qw( in_iprange );
23
23
24
$ENV{REMOTE_ADDR} = '192.168.1.30';
24
$ENV{REMOTE_ADDR} = '192.168.1.30';
25
25
26
ok(in_iprange("192.168.1.30"), 'simple single ip matching remote ip');
26
is( 1, in_iprange("192.168.1.30"), 'simple single ip matching remote ip' );
27
ok(!in_iprange("192.168.1.31"), 'simple single ip not match remote ip');
27
is( 0, in_iprange("192.168.1.31"), 'simple single ip not match remote ip' );
28
ok(in_iprange("192.168.1.1/24"), 'simple ip range/24 with remote ip in it');
28
is( 1, in_iprange("192.168.1.1/24"), 'simple ip range/24 with remote ip in it' );
29
ok(!in_iprange("192.168.2.1/24"), 'simple ip range/24 with remote ip not in it');
29
is( 0, in_iprange("192.168.2.1/24"), 'simple ip range/24 with remote ip not in it' );
30
ok(in_iprange("192.168.2.1/16"), 'simple ip range/16 with remote ip in it');
30
is( 1, in_iprange("192.168.2.1/16"), 'simple ip range/16 with remote ip in it' );
31
ok(!in_iprange("192.168.1.10-30"), 'invalidly represented IP range with remote ip in it');
31
is( 0, in_iprange("192.168.1.10-30"), 'invalidly represented IP range with remote ip in it' );
32
ok(in_iprange("192.168.1.10-192.168.1.30"), 'validly represented ip range with remote ip in it');
32
is( 1, in_iprange("192.168.1.10-192.168.1.30"), 'validly represented ip range with remote ip in it' );
33
ok(in_iprange("127.0.0.1 192.168.1.30 192.168.2.10-192.168.2.25"), 'multiple ips and ranges, including the remote ip');
33
is( 1, in_iprange("127.0.0.1 192.168.1.30 192.168.2.10-192.168.2.25"), 'multiple ips and ranges, including the remote ip' );
34
ok(!in_iprange("127.0.0.1 8.8.8.8 192.168.2.1/24 192.168.3.1/24 192.168.1.1-192.168.1.29"), "multiple ip and ip ranges, with the remote ip in none of them");
34
is( 0, in_iprange("127.0.0.1 8.8.8.8 192.168.2.1/24 192.168.3.1/24 192.168.1.1-192.168.1.29" ), "multiple ip and ip ranges, with the remote ip in none of them" );
35
ok(in_iprange(""), "blank list given, no preference set - implies everything goes through.");
35
is( 1, in_iprange(""), "blank list given, no preference set - implies everything goes through." );
36
ok(in_iprange(), "no list given, no preference set - implies everything goes through.");
36
is( 1, in_iprange(), "no list given, no preference set - implies everything goes through." );
37
ok(in_iprange("192.168.1.1/36"), 'simple invalid ip range/36 with remote ip in it');
37
is( 0, in_iprange("192.168.1.1/36"), 'simple invalid ip range/36 with remote ip in it' );
38
is( 1, in_iprange("192.168.1."), 'simple ip range missing last octet with remote ip in it' );
39
is( 1, in_iprange("192.168.1.*"), 'simple ip range with "*" with remote ip in it.  Undocumented feature; this should not work, but it does.' );
38
- 

Return to bug 28657