Completed
Push — master ( 7c8092...97052d )
by -
01:44
created

NaxsiWhitelist.validate()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
cc 1
crap 1
1 1
import re
2
3 1
from spike.model import db
4 1
from shlex import shlex
5
6 1
from spike.model.naxsi_rules import NaxsiRules
7 1
from flask import url_for
8
9 1
10 1
class NaxsiWhitelist(db.Model):
11 1
    __bind_key__ = 'rules'
12
    __tablename__ = 'naxsi_whitelist'
13 1
14 1
    id = db.Column(db.Integer, primary_key=True)
15 1
    wid = db.Column(db.String, nullable=False, unique=True)
16 1
    mz = db.Column(db.String(1024), nullable=False)
17 1
    negative = db.Column(db.Integer, nullable=False, server_default='0')
18 1
    active = db.Column(db.Integer, nullable=False, server_default='1')
19 1
    timestamp = db.Column(db.Integer, nullable=False)
20
    whitelistset = db.Column(db.String(1024), nullable=False)
21 1
22 1
    def __init__(self, wid='0', mz='', active=0, negative=0, whitelistset='', timestamp=0):
23 1
        self.wid = wid
24 1
        self.mz = mz
25 1
        self.active = active
26 1
        self.negative = negative
27 1
        self.whitelistset = whitelistset
28 1
        self.timestamp = timestamp
29 1
        self.warnings = []
30
        self.error = []
31 1
32 1
    def __str__(self):
33
        return 'BasicRule {}wl:{} "mz:{}";'.format('negative ' if self.negative else ' ', self.wid, self.mz)
34 1
35 1
    def __validate_id(self, wid):
36
        if not re.match(r'(\-?\d+,)*\-?\d+', wid):
37
            self.error.append('Illegal character in the whitelist id.')
38 1
            return False
39 1
        self.wid = wid
40
        return True
41 1
42
    def __validate_mz(self, mz):
43 1
        # Borrow '__validate_matchzone' from naxsi_rules.py ?
44 1
        self.mz = mz
45
        return True
46 1
47 1
    def parse(self, str_wl):
48 1
        self.warnings = list()
49
        self.error = list()
50 1
51 1
        lexer = shlex(str_wl)
52 1
        lexer.whitespace_split = True
53
        split = list(iter(lexer.get_token, ''))
54 1
55 1
        for piece in split:
56 1
            if piece == ';':
57 1
                continue
58 1
            elif piece.startswith(('"', "'")) and (piece[0] == piece[-1]):  # remove (double-)quotes
59
                piece = piece[1:-1]
60 1
61 1
            if piece == 'BasicRule':
62 1
                continue
63 1
            elif piece.startswith('wl:'):
64 1
                self.__validate_id(piece[3:])
65 1
            elif piece.startswith('mz:'):
66 1
                self.__validate_mz(piece[3:])
67
            elif piece == 'negative':
68
                self.negative = True
69 1
            else:
70 1
                self.error.append('Unknown fragment: {}'.format(piece))
71
                return False
72 1
73
        if 'BasicRule' not in split:
74
            self.error.append("No 'BasicRule' keyword in {}".format(str_wl))
75
            return False
76 1
77
        return True
78 1
79 1
    def validate(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
80 1
        return True
81 1
82
    def explain(self):
83
        def __linkify_rule(rid):
84 1
            if NaxsiRules.query.filter(NaxsiRules.sid == self.wid).first() is None:
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
85 1
                return rid
86 1
            return '<a href="{}">{}</a>'.format(url_for('rules.view', sid=rid), self.wid)
87 1
88
        if self.wid == '0':
89
            ret = 'Whitelist all rules'
90
        elif self.wid.isdigit():
91
            ret = 'Whitelist the rule {}'.format(__linkify_rule(self.wid))
92
        else:
93
            zones = list()
94
            for rid in self.wid.split(','):
95
                if rid.startswith('-'):
96
                    zones.append('except the rule {}'.format(__linkify_rule(rid[1:])))
97 1
                else:
98 1
                    zones.append('the rule {}'.format(__linkify_rule(rid)))
99
            ret = 'Whitelist '+ ', '.join(zones)
100 1
101
        if not self.mz:
102
            return ret + '.'
103
104
        return ret + ' if matching in {}.'.format(self.mz)
105