1
<?php
2
/**
3
 * This file is part of the Shieldon package.
4
 *
5
 * (c) Terry L. <contact@terryl.in>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 * 
10
 * php version 7.1.0
11
 * 
12
 * @category  Web-security
13
 * @package   Shieldon
14
 * @author    Terry Lin <contact@terryl.in>
15
 * @copyright 2019 terrylinooo
16
 * @license   https://github.com/terrylinooo/shieldon/blob/2.x/LICENSE MIT
17
 * @link      https://github.com/terrylinooo/shieldon
18
 * @see       https://shieldon.io
19
 */
20

21
declare(strict_types=1);
22

23
namespace Shieldon\Firewall\Kernel;
24

25
use Shieldon\Firewall\Kernel;
26
use Shieldon\Firewall\Component\ComponentProvider;
27
use Shieldon\Firewall\Component\TrustedBot;
28
use Shieldon\Firewall\Component\Ip;
29

30
/*
31
 * @since 1.0.0
32
 */
33
trait ComponentTrait
34
{
35
    /**
36
     *   Public methods       | Desctiotion
37
     *  ----------------------|---------------------------------------------
38
     *   setComponent         | Set a commponent.
39
     *   getComponent         | Get a component instance from component's container.
40
     *   disableComponents    | Disable all components.
41
     *  ----------------------|---------------------------------------------
42
     */
43

44
    /**
45
     * Get a class name without namespace string.
46
     *
47
     * @param object $instance Class
48
     * 
49
     * @return string
50
     */
51
    abstract protected function getClassName($instance): string;
52

53
    /**
54
     * Start an action for this IP address, allow or deny, and give a reason for it.
55
     *
56
     * @param int    $actionCode The action code. - 0: deny, 1: allow, 9: unban.
57
     * @param string $reasonCode The response code.
58
     * @param string $assignIp   The IP address.
59
     *
60
     * @return void
61
     */
62
    abstract protected function action(int $actionCode, int $reasonCode, string $assignIp = ''): void;
63

64
    /**
65
     * Deal with online sessions.
66
     *
67
     * @param int $statusCode The response code.
68
     *
69
     * @return int The response code.
70
     */
71
    abstract protected function sessionHandler($statusCode): int;
72

73
    /**
74
     * Save and return the result identifier.
75
     * This method is for passing value from traits.
76
     *
77
     * @param int $resultCode The result identifier.
78
     *
79
     * @return int
80
     */
81
    abstract protected function setResultCode(int $resultCode): int;
82

83
    /**
84
     * Container for Shieldon components.
85
     *
86
     * @var array
87
     */
88
    public $component = [];
89

90
    /**
91
     * Set a commponent.
92
     *
93
     * @param ComponentProvider $instance The component instance.
94
     *
95
     * @return void
96
     */
97 3
    public function setComponent(ComponentProvider $instance): void
98
    {
99 3
        $class = $this->getClassName($instance);
100 3
        $this->component[$class] = $instance;
101
    }
102

103
    /**
104
     * Get a component instance from component's container.
105
     *
106
     * @param string $name The component's class name.
107
     *
108
     * @return ComponentProvider|null
109
     */
110 3
    public function getComponent(string $name)
111
    {
112 3
        if (!isset($this->component[$name])) {
113 3
            return null;
114
        }
115

116 3
        return $this->component[$name];
117
    }
118

119
    /**
120
     * Disable all components.
121
     *
122
     * @return void
123
     */
124 3
    public function disableComponents(): void
125
    {
126 3
        $this->component = [];
127
    }
128

129
    /*
130
    |--------------------------------------------------------------------------
131
    | Stage in Kernel
132
    |--------------------------------------------------------------------------
133
    | The below methods are used in "process" method in Kernel.
134
    */
135

136
    /**
137
     * Initialize components.
138
     *
139
     * @return void
140
     */
141 3
    protected function initComponents()
142
    {
143 3
        foreach (array_keys($this->component) as $name) {
144 3
            $this->component[$name]->setIp($this->ip);
145 3
            $this->component[$name]->setRdns($this->rdns);
146

147
            // Apply global strict mode to all components by `strictMode()` if nesscessary.
148 3
            if (isset($this->strictMode)) {
149 3
                $this->component[$name]->setStrict($this->strictMode);
150
            }
151
        }
152
    }
153

154
    /**
155
     * Check if current IP is trusted or not.
156
     *
157
     * @return bool
158
     */
159 3
    protected function isTrustedBot()
160
    {
161 3
        $trustedBot = $this->getComponent('TrustedBot');
162

163 3
        if ($trustedBot instanceof TrustedBot) {
164

165
            // We want to put all the allowed robot into the rule list, so that the checking of IP's resolved hostname 
166
            // is no more needed for that IP.
167 3
            if ($trustedBot->isAllowed()) {
168

169 3
                if ($trustedBot->isGoogle()) {
170
                    // Add current IP into allowed list, because it is from real Google domain.
171 3
                    $this->action(
172 3
                        Kernel::ACTION_ALLOW,
173 3
                        Kernel::REASON_IS_GOOGLE
174
                    );
175

176 3
                } elseif ($trustedBot->isBing()) {
177
                    // Add current IP into allowed list, because it is from real Bing domain.
178 3
                    $this->action(
179 3
                        Kernel::ACTION_ALLOW,
180 3
                        Kernel::REASON_IS_BING
181
                    );
182

183 3
                } elseif ($trustedBot->isYahoo()) {
184
                    // Add current IP into allowed list, because it is from real Yahoo domain.
185 3
                    $this->action(
186 3
                        Kernel::ACTION_ALLOW,
187 3
                        Kernel::REASON_IS_YAHOO
188
                    );
189

190
                } else {
191
                    // Add current IP into allowed list, because you trust it.
192
                    // You have already defined it in the settings.
193 3
                    $this->action(
194 3
                        Kernel::ACTION_ALLOW,
195 3
                        Kernel::REASON_IS_SEARCH_ENGINE
196
                    );
197
                }
198
                // Allowed robots not join to our traffic handler.
199 3
                $this->setResultCode(Kernel::RESPONSE_ALLOW);
200 3
                return true;
201
            }
202
        }
203 3
        return false;
204
    }
205

206
    /**
207
     * Check whether the IP is fake search engine or not.
208
     * The method "isTrustedBot()" must be executed before this method.
209
     *
210
     * @return bool
211
     */
212 3
    protected function isFakeRobot(): bool
213
    {
214 3
        $trustedBot = $this->getComponent('TrustedBot');
215

216 3
        if ($trustedBot instanceof TrustedBot) {
217 3
            if ($trustedBot->isFakeRobot()) {
218 3
                $this->action(
219 3
                    Kernel::ACTION_DENY,
220 3
                    Kernel::REASON_COMPONENT_TRUSTED_ROBOT
221
                );
222 3
                $this->setResultCode(Kernel::RESPONSE_DENY);
223 3
                return true;
224
            }
225
        }
226 3
        return false;
227
    }
228

229
    /**
230
     * Check whether the IP is handled by IP compoent or not.
231
     *
232
     * @return bool
233
     */
234 3
    protected function isIpComponent(): bool
235
    {
236 3
        $ipComponent = $this->getComponent('Ip');
237

238 3
        if ($ipComponent instanceof Ip) {
239

240 3
            $result = $ipComponent->check($this->ip);
241

242 3
            if (!empty($result)) {
243

244 3
                switch ($result['status']) {
245

246 3
                    case 'allow':
247 3
                        $actionCode = Kernel::ACTION_ALLOW;
248 3
                        $reasonCode = $result['code'];
249 3
                        break;
250
    
251
                    
252 3
                    case 'deny':
253
                    default:
254 3
                        $actionCode = Kernel::ACTION_DENY;
255 3
                        $reasonCode = $result['code']; 
256 3
                        break;
257
                }
258

259 3
                $this->action($actionCode, $reasonCode);
260

261
                // $resultCode = $actionCode
262 3
                $this->setResultCode($this->sessionHandler($actionCode));
263 3
                return true;
264
            }
265
        }
266 3
        return false;
267
    }
268

269
    /**
270
     * Check other compoents.
271
     *
272
     * @return bool
273
     */
274 3
    protected function isComponents()
275
    {
276 3
        foreach ($this->component as $component) {
277

278 3
            if ($component->isDenied()) {
279

280 3
                $this->action(
281 3
                    Kernel::ACTION_DENY,
282 3
                    $component->getDenyStatusCode()
283
                );
284

285 3
                $this->setResultCode(Kernel::RESPONSE_DENY);
286 3
                return true;
287
            }
288
        }
289 3
        return false;
290
    }
291
}

Read our documentation on viewing source code .

Loading