Completed
Push — master ( e0b5f5...6e63d2 )
by
unknown
12s
created

ospd_openvas.wrapper.OSPDopenvas.stop_scan()   A

Complexity

Conditions 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 14
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nop 2
dl 14
loc 14
rs 9.95
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
# Description:
3
# Setup for the OSP OpenVAS Server
4
#
5
# Authors:
6
# Juan José Nicola <[email protected]>
7
#
8
# Copyright:
9
# Copyright (C) 2018 Greenbone Networks GmbH
10
#
11
# This program is free software; you can redistribute it and/or
12
# modify it under the terms of the GNU General Public License
13
# as published by the Free Software Foundation; either version 2
14
# of the License, or (at your option) any later version.
15
#
16
# This program is distributed in the hope that it will be useful,
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
# GNU General Public License for more details.
20
#
21
# You should have received a copy of the GNU General Public License
22
# along with this program; if not, write to the Free Software
23
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
25
import subprocess
26
import time
27
import os
28
import signal
29
import psutil
30
import uuid
0 ignored issues
show
introduced by
standard import "import uuid" should be placed before "import psutil"
Loading history...
31
32
from ospd.ospd import OSPDaemon, logger
33
from ospd.misc import main as daemon_main
34
from ospd.misc import target_str_to_list
35
from ospd_openvas import __version__
36
37
import ospd_openvas.nvticache as nvti
38
import ospd_openvas.openvas_db as openvas_db
39
40
OSPD_DESC = """
41
This scanner runs 'OpenVAS Scanner' to scan the target hosts.
42
43
OpenVAS (Open Vulnerability Assessment System) is a powerful scanner
44
for vulnerabilities in IT infrastrucutres. The capabilities include
45
unauthzenticated scanning as well as authneticated scanning for
46
various types of systems and services.
47
48
For more details about OpenVAS see the OpenVAS homepage:
49
http://www.openvas.org/
50
51
The current version of ospd-openvas is a simple frame, which sends
52
the server parameters to the Greenbone Vulnerability Manager (GVM) and checks
53
the existence of OpenVAS Scanner binary. But it can not run scans yet.
54
"""
55
56
MAIN_KBINDEX = None
57
58
OSPD_PARAMS = {
59
    'auto_enable_dependencies': {
60
        'type': 'boolean',
61
        'name': 'auto_enable_dependencies',
62
        'default': 1,
63
        'mandatory': 1,
64
        'description': 'Automatically enable the plugins that are depended on',
65
    },
66
    'cgi_path': {
67
        'type': 'string',
68
        'name': 'cgi_path',
69
        'default': '/cgi-bin:/scripts',
70
        'mandatory': 1,
71
        'description': 'Look for default CGIs in /cgi-bin and /scripts',
72
    },
73
    'checks_read_timeout': {
74
        'type': 'integer',
75
        'name': 'checks_read_timeout',
76
        'default': 5,
77
        'mandatory': 1,
78
        'description': ('Number  of seconds that the security checks will ' +
79
                        'wait for when doing a recv()'),
80
    },
81
    'drop_privileges': {
82
        'type': 'boolean',
83
        'name': 'drop_privileges',
84
        'default': 0,
85
        'mandatory': 1,
86
        'description': '',
87
    },
88
    'network_scan': {
89
        'type': 'boolean',
90
        'name': 'network_scan',
91
        'default': 0,
92
        'mandatory': 1,
93
        'description': '',
94
    },
95
    'non_simult_ports': {
96
        'type': 'string',
97
        'name': 'non_simult_ports',
98
        'default': '139, 445, 3389, Services/irc',
99
        'mandatory': 1,
100
        'description': ('Prevent to make two connections on the same given ' +
101
                        'ports at the same time.'),
102
    },
103
    'open_sock_max_attempts': {
104
        'type': 'integer',
105
        'name': 'open_sock_max_attempts',
106
        'default': 5,
107
        'mandatory': 0,
108
        'description': ('Number of unsuccessful retries to open the socket ' +
109
                        'before to set the port as closed.'),
110
    },
111
    'timeout_retry': {
112
        'type': 'integer',
113
        'name': 'timeout_retry',
114
        'default': 5,
115
        'mandatory': 0,
116
        'description': ('Number of retries when a socket connection attempt ' +
117
                        'timesout.'),
118
    },
119
    'optimize_test': {
120
        'type': 'integer',
121
        'name': 'optimize_test',
122
        'default': 5,
123
        'mandatory': 0,
124
        'description': ('By default, openvassd does not trust the remote ' +
125
                        'host banners.'),
126
    },
127
    'plugins_timeout': {
128
        'type': 'integer',
129
        'name': 'plugins_timeout',
130
        'default': 5,
131
        'mandatory': 0,
132
        'description': 'This is the maximum lifetime, in seconds of a plugin.',
133
    },
134
    'report_host_details': {
135
        'type': 'boolean',
136
        'name': 'report_host_details',
137
        'default': 1,
138
        'mandatory': 1,
139
        'description': '',
140
    },
141
    'safe_checks': {
142
        'type': 'boolean',
143
        'name': 'safe_checks',
144
        'default': 1,
145
        'mandatory': 1,
146
        'description': ('Disable the plugins with potential to crash ' +
147
                        'the remote services'),
148
    },
149
    'scanner_plugins_timeout': {
150
        'type': 'integer',
151
        'name': 'scanner_plugins_timeout',
152
        'default': 36000,
153
        'mandatory': 1,
154
        'description': 'Like plugins_timeout, but for ACT_SCANNER plugins.',
155
    },
156
    'time_between_request': {
157
        'type': 'integer',
158
        'name': 'time_between_request',
159
        'default': 0,
160
        'mandatory': 0,
161
        'description': ('Allow to set a wait time between two actions ' +
162
                        '(open, send, close).'),
163
    },
164
    'unscanned_closed': {
165
        'type': 'boolean',
166
        'name': 'unscanned_closed',
167
        'default': 1,
168
        'mandatory': 1,
169
        'description': '',
170
    },
171
    'unscanned_closed_udp': {
172
        'type': 'boolean',
173
        'name': 'unscanned_closed_udp',
174
        'default': 1,
175
        'mandatory': 1,
176
        'description': '',
177
    },
178
    'use_mac_addr': {
179
        'type': 'boolean',
180
        'name': 'use_mac_addr',
181
        'default': 0,
182
        'mandatory': 0,
183
        'description': 'To test the local network. ' +
184
                       'Hosts will be referred to by their MAC address.',
185
    },
186
    'vhosts': {
187
        'type': 'string',
188
        'name': 'vhosts',
189
        'default': '',
190
        'mandatory': 0,
191
        'description': '',
192
    },
193
    'vhosts_ip': {
194
        'type': 'string',
195
        'name': 'vhosts_ip',
196
        'default': '',
197
        'mandatory': 0,
198
        'description': '',
199
    },
200
}
201
202
203 View Code Duplication
class OSPDopenvas(OSPDaemon):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
204
205
    """ Class for ospd-openvas daemon. """
206
207
    def __init__(self, certfile, keyfile, cafile):
208
        """ Initializes the ospd-openvas daemon's internal data. """
209
210
        super(OSPDopenvas, self).__init__(certfile=certfile, keyfile=keyfile,
211
                                          cafile=cafile)
212
        self.server_version = __version__
213
        self.scanner_info['name'] = 'openvassd'
214
        self.scanner_info['version'] = ''  # achieved during self.check()
215
        self.scanner_info['description'] = OSPD_DESC
216
        for name, param in OSPD_PARAMS.items():
217
            self.add_scanner_param(name, param)
218
219
        if openvas_db.db_init() is False:
220
            logger.error('OpenVAS Redis Error: Not possible '
221
                         'to find db_connection.')
222
            raise Exception
223
224
        ctx = openvas_db.db_find(nvti.NVTICACHE_STR)
225
        if not ctx:
226
            self.redis_nvticache_init()
227
            ctx = openvas_db.db_find(nvti.NVTICACHE_STR)
228
        openvas_db.set_global_redisctx(ctx)
229
        self.load_vts()
230
231
    def parse_param(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...
232
        """ Set OSPD_PARAMS with the params taken from the openvas_scanner. """
233
        global OSPD_PARAMS
0 ignored issues
show
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
234
        bool_dict = {'no': 0, 'yes': 1}
235
236
        result = subprocess.check_output(['openvassd', '-s'],
237
                                         stderr=subprocess.STDOUT)
238
        result = result.decode('ascii')
239
        param_list = dict()
240
        for conf in result.split('\n'):
241
            elem = conf.split('=')
242
            if len(elem) == 2:
243
                value = str.strip(elem[1])
244
                if str.strip(elem[1]) in bool_dict:
245
                    value = bool_dict[value]
246
                param_list[str.strip(elem[0])] = value
247
        for elem in OSPD_PARAMS:
248
            if elem in param_list:
249
                OSPD_PARAMS[elem]['default'] = param_list[elem]
250
251
    def redis_nvticache_init(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...
252
        """ Loads NVT's metadata into Redis DB. """
253
        try:
254
            logger.debug('Loading NVTs in Redis DB')
255
            subprocess.check_call(['openvassd', '-C'])
256
        except subprocess.CalledProcessError as err:
257
            logger.error('OpenVAS Scanner failed to load NVTs.')
258
            raise err
259
260
    def load_vts(self):
261
        """ Load the NVT's OIDs and their filename into the vts
262
        global  dictionary. """
263
        oids = nvti.get_oids()
264
        str_out = True
265
        for oid in oids:
266
            vt_id = oid[1]
267
            filename = oid[0].split(':')
268
            ret = self.add_vt(vt_id,
269
                              name=filename[1],
270
                              vt_params=nvti.get_nvt_params(vt_id, str_out),
271
                              custom=nvti.get_nvt_metadata(vt_id, str_out))
272
            if ret == -1:
273
                logger.info("Dupplicated VT with OID: {0}".format(vt_id))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
274
            if ret == -2:
275
                logger.info("{0}: Invalid OID.".format(vt_id))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
276
277
    @staticmethod
278
    def get_custom_vt_as_xml_str(custom):
279
        """ Return custom since it is already formated as string. """
280
        return custom
281
282
    @staticmethod
283
    def get_params_vt_as_xml_str(vt_params):
284
        """ Return custom since it is already formated as string. """
285
        return vt_params
286
287
    def check(self):
288
        """ Checks that openvassd command line tool is found and
289
        is executable. """
290
        try:
291
            result = subprocess.check_output(['openvassd', '-V'],
292
                                             stderr=subprocess.STDOUT)
293
            result = result.decode('ascii')
294
        except OSError:
295
            # The command is not available
296
            return False
297
298
        if result is None:
299
            return False
300
301
        version = result.split('\n')
302
        if version[0].find('OpenVAS') < 0:
303
            return False
304
305
        self.parse_param()
306
        self.scanner_info['version'] = version[0]
307
308
        return True
309
310
    def update_progress(self, scan_id, target, msg):
311
        """ Calculate porcentage and update the scan status
312
        for the progress bar. """
313
        host_progress_dict = dict()
314
        prog = str.split(msg, '/')
315
        if float(prog[1]) == 0:
316
            return
317
        host_prog = (float(prog[0]) / float(prog[1])) * 100
318
        host_progress_dict[target] = host_prog
319
        total_host = len(target_str_to_list(target))
320
        self.set_scan_progress(scan_id,
321
                               sum(host_progress_dict.values()) / total_host)
322
323
    def get_openvas_status(self, scan_id, target):
324
        """ Get all status entries from redis kb. """
325
        res = openvas_db.get_status()
326
        while res:
327
            self.update_progress(scan_id, target, res)
328
            res = openvas_db.get_status()
329
330
    def get_openvas_result(self, scan_id):
331
        """ Get all result entries from redis kb. """
332
        res = openvas_db.get_result()
333
        while res:
334
            msg = res.split('|||')
335
            if msg[1] == '':
336
                host_aux = openvas_db.item_get_single('internal/ip')
337
            else:
338
                host_aux = msg[1]
339
            if msg[0] == 'ERRMSG':
340
                self.add_scan_error(scan_id, host=host_aux,
341
                                    name=msg[3], value=msg[4], port=msg[2])
342
            if msg[0] == 'LOG':
343
                self.add_scan_log(scan_id, host=host_aux, name=msg[3],
344
                                  value=msg[4], port=msg[2])
345
            if msg[0] == 'ALARM':
346
                self.add_scan_alarm(scan_id, host=host_aux, name=msg[3],
347
                                    value=msg[4], port=msg[2], qod='97',
348
                                    severity='7.5')
349
            res = openvas_db.get_result()
350
351
    def get_openvas_timestamp_scan_host(self, scan_id, target):
352
        """ Get start and end timestamp of a host scan from redis kb. """
353
        timestamp = openvas_db.get_host_scan_scan_end_time()
354
        if timestamp:
355
            self.add_scan_log(scan_id, host=target, name='HOST_END',
356
                              value=timestamp)
357
            return
358
        timestamp = openvas_db.get_host_scan_scan_start_time()
359
        if timestamp:
360
            self.add_scan_log(scan_id, host=target, name='HOST_START',
361
                              value=timestamp)
362
            return
363
364
    def scan_is_finished(self, scan_id):
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...
365
        """ Check if the scan has finished. """
366
        status = openvas_db.item_get_single(('internal/%s' % scan_id))
367
        return status == 'finished'
368
369
    def scan_is_stopped(self, scan_id):
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...
370
        """ Check if the parent process has recieved the stop_scan order.
371
        @in scan_id: ID to identify the scan to be stopped.
372
        @return 1 if yes, None in oder case.
373
        """
374
        ctx = openvas_db.kb_connect(dbnum=MAIN_KBINDEX)
375
        openvas_db.set_global_redisctx(ctx)
376
        status = openvas_db.item_get_single(('internal/%s' % scan_id))
377
        return status == 'stop_all'
378
379
    def stop_scan(self, scan_id):
380
        """ Set a key in redis to indicate the wrapper process that it
381
        must kill the childs. It is done through redis because this a new
382
        multiprocess instance and it is not possible to reach the variables
383
        of the grandchild process. Then, a clean up is performed before
384
        terminating. """
385
        ctx = openvas_db.db_find('internal/%s' % scan_id)
386
        openvas_db.set_global_redisctx(ctx)
387
        openvas_db.item_set_single(('internal/%s' % scan_id), ['stop_all', ])
388
        while 1:
389
            time.sleep(1)
390
            if openvas_db.item_get_single('internal/%s' % scan_id):
391
                continue
392
            break
393
394
    def do_cleanup(self, ovas_pid):
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...
395
        """ Send SIGUSR1 to OpenVAS process to stop the scan. """
396
        parent = psutil.Process(ovas_pid)
397
        children = parent.children(recursive=True)
398
        for process in children:
399
            if process.ppid() == int(ovas_pid):
400
                logger.debug('Stopping process: {0}'.format(process))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
401
                os.kill(process.pid, signal.SIGUSR1)
402
403
404
    @staticmethod
405
    def get_vts_in_groups(ctx, filters):
406
        """ Return a list of vts which match with the given filter.
407
408
        @input filters A list of filters. Each filter has key, operator and
409
                       a value. They are separated by a space.
410
                       Supported keys: family
411
        @return Return a list of vts which match with the given filter.
412
        """
413
        vts_list = list()
414
        oids = nvti.get_oids()
415
416
        for elem in filters:
417
            key, value = elem.split('=')
418
            for oid in oids:
419
                if key == 'family' and value == nvti.get_nvt_family(ctx, oid[1]):
420
                    vts_list.append(oid[1])
421
        return vts_list
422
423
424
    def process_vts(self, vts):
425
        """ Add single VTs and their parameters. """
426
        vts_list = []
427
        vts_params = []
428
        vtgroups = vts.pop('vtgroups')
429
430
        ctx = openvas_db.db_find(nvti.NVTICACHE_STR)
431
        openvas_db.set_global_redisctx(ctx)
432
        if vtgroups:
433
            vts_list = self.get_vts_in_groups(ctx, vtgroups)
434
435
        for memb in vts.items():
436
            vts_list.append(memb[0])
437
            nvt_name = nvti.get_nvt_name(ctx, memb[0])
438
            for i in memb[1].items():
439
                param = ["{0}[{1}]:{2}".format(nvt_name, i[1]['type'], i[0]),
440
                         str(i[1]['value'])]
441
                vts_params.append(param)
442
        return vts_list, vts_params
443
444
    @staticmethod
445
    def build_credentials_as_prefs(credentials):
446
        """ Parse the credential dictionary.
447
        @param credentials: Dictionary with the credentials.
448
449
        @return A list with the credentials in string format to be
450
                added to the redis KB.
451
        """
452
        cred_prefs_list = []
453
        for credential in credentials.items():
454
            service = credential[0]
455
            cred_params = credentials.get(service)
456
            cred_type = cred_params.get('type', '')
457
            username = cred_params.get('username', '')
458
            password = cred_params.get('password', '')
459
460
            if service == 'ssh':
461
                port = cred_params.get('port', '')
462
                cred_prefs_list.append('auth_port_ssh|||' +
463
                                       '{0}'.format(port))
464
                cred_prefs_list.append('SSH Authorization[entry]:SSH login ' +
465
                                       'name:|||{0}'.format(username))
466
                if cred_type == 'up':
467
                    cred_prefs_list.append('SSH Authorization[password]:' +
468
                                           'SSH password (unsafe!):|||' +
469
                                           '{0}'.format(password))
470
                else:
471
                    private = cred_params.get('private', '')
472
                    cred_prefs_list.append('SSH Authorization[password]:' +
473
                                           'SSH key passphrase:|||' +
474
                                           '{0}'.format(password))
475
                    cred_prefs_list.append('SSH Authorization[file]:' +
476
                                           'SSH private key:|||' +
477
                                           '{0}'.format(private))
478
            if service == 'smb':
479
                cred_prefs_list.append('SMB Authorization[entry]:SMB login:' +
480
                                       '|||{0}'.format(username))
481
                cred_prefs_list.append('SMB Authorization[password]:' +
482
                                       'SMB password :|||' +
483
                                       '{0}'.format(password))
484
            if service == 'esxi':
485
                cred_prefs_list.append('ESXi Authorization[entry]:ESXi login ' +
486
                                       'name:|||{0}'.format(username))
487
                cred_prefs_list.append('ESXi Authorization[password]:' +
488
                                       'ESXi login password:|||' +
489
                                       '{0}'.format(password))
490
491
            if service == 'snmp':
492
                community = cred_params.get('community', '')
493
                auth_algorithm = cred_params.get('auth_algorithm', '')
494
                privacy_password = cred_params.get('privacy_password', '')
495
                privacy_algorithm = cred_params.get('privacy_algorithm', '')
496
497
                cred_prefs_list.append('SNMP Authorization[password]:' +
498
                                       'SNMP Community:' +
499
                                       '{0}'.format(community))
500
                cred_prefs_list.append('SNMP Authorization[entry]:' +
501
                                       'SNMPv3 Username:' +
502
                                       '{0}'.format(username))
503
                cred_prefs_list.append('SNMP Authorization[password]:' +
504
                                       'SNMPv3 Password:' +
505
                                       '{0}'.format(password))
506
                cred_prefs_list.append('SNMP Authorization[radio]:' +
507
                                       'SNMPv3 Authentication Algorithm:' +
508
                                       '{0}'.format(auth_algorithm))
509
                cred_prefs_list.append('SNMP Authorization[password]:' +
510
                                       'SNMPv3 Privacy Password:' +
511
                                       '{0}'.format(privacy_password))
512
                cred_prefs_list.append('SNMP Authorization[radio]:' +
513
                                       'SNMPv3 Privacy Algorithm:' +
514
                                       '{0}'.format(privacy_algorithm))
515
516
        return cred_prefs_list
517
518
    def exec_scan(self, scan_id, target):
0 ignored issues
show
Comprehensibility introduced by
This function exceeds the maximum number of variables (30/15).
Loading history...
519
        """ Starts the OpenVAS scanner for scan_id scan. """
520
        global MAIN_KBINDEX
0 ignored issues
show
Coding Style introduced by
Usage of the global statement should be avoided.

Usage of global can make code hard to read and test, its usage is generally not recommended unless you are dealing with legacy code.

Loading history...
521
        ports = self.get_scan_ports(scan_id, target)
522
        if not ports:
523
            self.add_scan_error(scan_id, name='', host=target,
524
                                value='No port list defined.')
525
            return 2
526
527
        # Get scan options
528
        options = self.get_scan_options(scan_id)
529
        prefs_val = []
530
        ctx = openvas_db.kb_new()
531
        openvas_db.set_global_redisctx(ctx)
532
        MAIN_KBINDEX = openvas_db.DB_INDEX
533
534
        # To avoid interference between scan process during a parallel scanning
535
        # new uuid is used internaly for each scan.
536
        openvas_scan_id = str(uuid.uuid4())
537
        openvas_db.item_add_single(('internal/%s' % openvas_scan_id), ['new', ])
538
539
        # Set scan preferences
540
        for item in options.items():
541
            item_type = ''
542
            if item[0] in OSPD_PARAMS:
543
                item_type = OSPD_PARAMS[item[0]].get('type')
544
            if item_type == 'boolean' and item[1] == 1:
545
                val = 'yes'
546
            else:
547
                val = str(item[1])
548
            prefs_val.append(item[0] + "|||" + val)
549
        openvas_db.item_add_single(str('internal/%s/scanprefs' % (openvas_scan_id)),
550
                                   prefs_val)
551
552
        # Store MAIN_KBINDEX as global preference
553
        ov_maindbid = ('ov_maindbid|||%d' % MAIN_KBINDEX)
554
        openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id),
555
                                   [ov_maindbid, ])
556
557
        # Set target
558
        target_aux = ('TARGET|||%s' % target)
559
        openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id),
560
                                   [target_aux, ])
561
        # Set port range
562
        port_range = ('port_range|||%s' % ports)
563
        openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id),
564
                                   [port_range, ])
565
566
        # Set credentials
567
        credentials = self.get_scan_credentials(scan_id, target)
568
        if credentials:
569
            cred_prefs = self.build_credentials_as_prefs(credentials)
570
            openvas_db.item_add_single(str('internal/%s/scanprefs' % openvas_scan_id),
571
                                       cred_prefs)
572
573
        # Set plugins to run
574
        nvts = self.get_scan_vts(scan_id)
575
        if nvts != '':
576
            nvts_list, nvts_params = self.process_vts(nvts)
577
            # Select the scan KB again.
578
            ctx.execute_command('SELECT '+ str(MAIN_KBINDEX))
579
            openvas_db.set_global_redisctx(ctx)
580
            # Add nvts list
581
            separ = ';'
582
            plugin_list = ('plugin_set|||%s' % separ.join(nvts_list))
583
            openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id),
584
                                       [plugin_list, ])
585
            # Add nvts parameters
586
            for elem in nvts_params:
587
                item = ('%s|||%s' % (elem[0], elem[1]))
588
                openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id),
589
                                           [item, ])
590
        else:
591
            openvas_db.release_db(MAIN_KBINDEX)
592
            self.add_scan_error(scan_id, name='', host=target,
593
                                value='No VTS to run.')
594
            return 2
595
596
        # Create a general log entry about executing OpenVAS
597
        # It is important to send at least one result, otherwise
598
        # the host details won't be stored.
599
        self.add_scan_log(scan_id, host=target, name='OpenVAS summary',
600
                          value='An OpenVAS Scanner was started for %s.'
601
                          % target)
602
603
        self.add_scan_log(scan_id, host=target, name='KB location Found',
604
                          value='KB location path was found: %s.'
605
                          % openvas_db.DB_ADDRESS)
606
607
        self.add_scan_log(scan_id, host=target, name='Feed Update',
608
                          value='Feed version: %s.'
609
                          % nvti.get_feed_version())
610
611
        cmd = ['openvassd', '--scan-start', openvas_scan_id]
612
        try:
613
            result = subprocess.Popen(cmd, shell=False)
614
        except OSError:
615
            # the command is not available
616
            return False
617
618
        ovas_pid = result.pid
619
        logger.debug('pid = {0}'.format(ovas_pid))
0 ignored issues
show
introduced by
Use formatting in logging functions and pass the parameters as arguments
Loading history...
620
621
        # Wait until the scanner starts and loads all the preferences.
622
        while openvas_db.item_get_single('internal/'+ openvas_scan_id) == 'new':
623
            time.sleep(1)
624
625
        no_id_found = False
626
        while True:
627
            time.sleep(3)
628
629
            # Check if the client stopped the whole scan
630
            if self.scan_is_stopped(openvas_scan_id):
631
                self.do_cleanup(ovas_pid)
632
633
            ctx = openvas_db.kb_connect(MAIN_KBINDEX)
634
            openvas_db.set_global_redisctx(ctx)
635
            dbs = openvas_db.item_get_set('internal/dbindex')
636
            for i in list(dbs):
637
                if i == MAIN_KBINDEX:
638
                    continue
639
                ctx.execute_command('SELECT '+ str(i))
640
                openvas_db.set_global_redisctx(ctx)
641
                id_aux = ctx.execute_command('srandmember internal/scan_id')
642
                if not id_aux:
643
                    continue
644
                if id_aux == openvas_scan_id:
645
                    no_id_found = False
646
                    self.get_openvas_timestamp_scan_host(scan_id, target)
647
                    self.get_openvas_result(scan_id)
648
                    self.get_openvas_status(scan_id, target)
649
                    if self.scan_is_finished(openvas_scan_id):
650
                        openvas_db.release_db(i)
651
                        ctx.execute_command('SELECT '+ str(MAIN_KBINDEX))
652
                        openvas_db.remove_set_member('internal/dbindex', i)
653
654
            # Scan end. No kb in use for this scan id
655
            if no_id_found:
656
                break
657
            no_id_found = True
658
659
        # Delete keys from KB related to this scan task.
660
        openvas_db.release_db(MAIN_KBINDEX)
661
        return 1
662
663
664
def main():
665
    """ OSP openvas main function. """
666
    daemon_main('OSPD - openvas wrapper', OSPDopenvas)
667