aboutsummaryrefslogtreecommitdiff
path: root/lib/models/WebserviceAccessRule.php
blob: 857830a3abb3cbfa8d67540545b892b920938a6c (plain)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<?php
/**
 * WebserviceAccessRule.php
 * model class for table webservice_access_rules
 * this class represents one record of the table webservice_access_rules
 * the column ip_range is converted from a comma separated list to an ArrayObject and vice-versa,
 * to allow array-like access
 *
 * Example:
 * @code
 * $rule = WebserviceAccessRule::find($id);
 * echo $rule['ip_range']; //prints out e.g. 127.0.0.1
 * $rule['ip_range'][] = '192.168.19.0/8';
 * echo $rule['ip_range']; //prints out 127.0.0.1,192.168.19.0/8
 * @endcode
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      André Noack <noack@data-quest.de>
 * @copyright   2011 Stud.IP Core-Group
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Stud.IP
 *
 * @property string $api_key database column
 * @property string $method database column
 * @property CSVArrayObject $ip_range database column
 * @property string $type database column
 * @property int $id database column
 * @property int|null $mkdate database column
 * @property int|null $chdate database column
 */
class WebserviceAccessRule extends SimpleORMap
{
    protected static function configure($config = [])
    {
        $config['db_table'] = 'webservice_access_rules';
        $config['serialized_fields']['ip_range'] = CSVArrayObject::class;
        parent::configure($config);
    }

    /**
     * returns all rules for an given api key
     *
     * @param string $api_key
     * @return array of WebserviceAccessRule objects
     */
    static function findByApiKey($api_key)
    {
        return self::findByapi_key($api_key, " ORDER BY type");
    }

    /**
     * returns all rules in db sorted by api key
     *
     * @return array of WebserviceAccessRule objects
     */
    static function findAll()
    {
        return self::findBySQL("1 ORDER BY api_key, type");
    }

    /**
     * Checks for given api key, methodname and IP Address if access
     * is granted or not
     *
     * @param string $api_key an api key
     * @param string $method a name of an webservice method
     * @param string $ip an IP Address
     * @return boolean returns true if access fpr given params is allowed
     */
    static function checkAccess($api_key, $method, $ip)
    {
        $rules = self::findByApiKey($api_key);
        $access = false;
        foreach ($rules as $rule) {
            if ($rule->type == 'allow'
                && $rule->checkIpInRange($ip)
                && $rule->checkMethodName($method)) {
                $access = true;
            }
            if ($rule->type == 'deny'
                && $rule->checkIpInRange($ip)
                && $rule->checkMethodName($method)) {
                $access = false;
            }
        }
        return $access;
    }

    /**
     * checks, if a given IP Address is in the range specified
     * for this rule. If there is no specified range, it returns true
     *
     * @param string $check_ip an IP Address
     * @return boolean true if given Address is in specified range
     */
    function checkIpInRange($check_ip)
    {
        $ip_addr = inet_pton($check_ip);

        if (!count($this->ip_range)) {
            return true;
        }
        foreach ($this->ip_range as $range) {
            if (strpos($range, '/') !== false) {
                list($range, $bits) = explode('/', $range);
                $range = inet_pton($range) ?: '';
                $mask = str_repeat(chr(0), strlen($range));

                for ($i = 0; $i < strlen($mask); ++$i) {
                    if ($bits >= 8) {
                        $bits -= 8;
                    } else {
                        $mask[$i] = chr((1 << 8 - $bits) - 1);
                        $bits = 0;
                    }
                }

                $ip_start = $range & ~$mask;
                $ip_end = $range | $mask;
            } else {
                $ip_start = inet_pton($range);
                $ip_end = inet_pton($range);
            }

            if (strcmp($ip_start, $ip_addr) <= 0 && strcmp($ip_addr, $ip_end) <= 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * checks, if the specified method name for this rule
     * is part of the given one.
     * If there is no specified method name, it returns true
     *
     *
     * @param string $method a webservice method name
     * @return boolean true if given name matches the specified
     */
    function checkMethodName($method)
    {
        return ($method && (!$this->method || mb_strpos($method, $this->method) !== false));
    }
}