Passed
Pull Request — master (#140)
by
unknown
01:49
created

gvmtools.pyshell   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 103
dl 0
loc 201
rs 10
c 0
b 0
f 0
wmc 23

3 Functions

Rating   Name   Duplication   Size   Complexity  
A enter_interactive_mode() 0 5 1
C main() 0 79 11
A load() 0 15 2

8 Methods

Rating   Name   Duplication   Size   Complexity  
A Arguments.get() 0 2 1
A Arguments.__init__() 0 2 1
A Arguments.__setattr__() 0 5 2
A Arguments.__getattr__() 0 2 1
A Arguments.__getitem__() 0 2 1
A Arguments.__repr__() 0 2 1
A Help.__repr__() 0 3 1
A Help.__call__() 0 2 1
1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2018 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
import code
20
import logging
21
import os
22
import sys
23
24
from gvm import get_version as get_gvm_version
25
from gvm.protocols.latest import Gmp, Osp
26
from gvm.transforms import EtreeCheckCommandTransform
27
28
from gvmtools import get_version
29
from gvmtools.helper import authenticate
30
from gvmtools.parser import create_parser, create_connection, PROTOCOL_OSP
31
32
__version__ = get_version()
33
__api_version__ = get_gvm_version()
34
35
logger = logging.getLogger(__name__)
36
37
HELP_TEXT = """
38
    Command line tool to access services via GMP (Greenbone Management
39
    Protocol) and OSP (Open Scanner Protocol)
40
41
    gvm-pyshell provides an interactive shell for GMP and OSP services
42
    and can be used to execute custom OSP/GMP scripts.
43
44
    Example:
45
        >>> tasks = gmp.get_tasks()
46
        >>> task_names = tasks.xpath('task/name/text()')
47
        >>> print(task_names)
48
        ['Scan Task']
49
50
    The interactive shell can be exited with:
51
        Ctrl + D on Linux  or
52
        Ctrl + Z on Windows
53
54
    The protocol specifications for GMP and OSP are available at:
55
      https://docs.greenbone.net/index.html#api_documentation"""
56
57
58
class Help(object):
59
    """Help class to overwrite the help function from python itself.
60
    """
61
62
    def __call__(self):
63
        return print(HELP_TEXT)
64
65
    def __repr__(self):
66
        # do pwd command
67
        return HELP_TEXT
68
69
70
class Arguments:
71
72
    def __init__(self, **kwargs):
73
        self._args = kwargs
74
75
    def get(self, key):
76
        return self._args[key]
77
78
    def __getattr__(self, key):
79
        return self.get(key)
80
81
    def __setattr__(self, name, value):
82
        if name.startswith('_'):
83
            super().__setattr__(name, value)
84
        else:
85
            self._args[name] = value
86
87
    def __getitem__(self, key):
88
        return self.get(key)
89
90
    def __repr__(self):
91
        return repr(self._args)
92
93
94
def main():
95
    parser = create_parser(
96
        description=HELP_TEXT, logfilename='gvm-pyshell.log')
97
98
    parser.add_protocol_argument()
99
100
    parser.add_argument(
101
        '-i', '--interactive', action='store_true', default=False,
102
        help='Start an interactive Python shell')
103
104
    parser.add_argument(
105
        'scriptname', nargs='?', metavar="SCRIPT",
106
        help='Path to script to be preloaded (example: myscript.gmp)')
107
    parser.add_argument(
108
        'scriptargs', nargs='*', metavar="ARG",
109
        help='Arguments for preloaded script')
110
111
    args = parser.parse_args()
112
113
    if 'socket' in args.connection_type and args.sockpath:
114
        print('The --sockpath parameter has been deprecated. Please use '
115
              '--socketpath instead', file=sys.stderr)
116
117
    connection = create_connection(**vars(args))
118
119
    transform = EtreeCheckCommandTransform()
120
121
    global_vars = {
122
        'help': Help(),
123
        '__version__': __version__,
124
        '__api_version__': __api_version__,
125
    }
126
127
    username = None
128
    password = None
129
130
    if args.protocol == PROTOCOL_OSP:
131
        protocol = Osp(connection, transform=transform)
132
        global_vars['osp'] = protocol
133
        global_vars['__name__'] = '__osp__'
134
    else:
135
        protocol = Gmp(connection, transform=transform)
136
        global_vars['gmp'] = protocol
137
        global_vars['__name__'] = '__gmp__'
138
139
        if args.gmp_username:
140
            (username, password) = authenticate(
141
                protocol, username=args.gmp_username,
142
                password=args.gmp_password)
143
144
    shell_args = Arguments(
145
        username=username, password=password)
146
147
    global_vars['args'] = shell_args
148
149
    with_script = args.scriptname and len(args.scriptname) > 0
150
151
    if with_script:
152
        argv = [os.path.abspath(args.scriptname), *args.scriptargs]
153
        shell_args.argv = argv
154
        # for backwards compatibility we add script here
155
        shell_args.script = argv
156
157
    no_script_no_interactive = not args.interactive and not with_script
158
    script_and_interactive = args.interactive and with_script
159
    only_interactive = not with_script and args.interactive
160
    only_script = not args.interactive and with_script
161
162
    if only_interactive or no_script_no_interactive:
163
        enter_interactive_mode(global_vars)
164
165
    if script_and_interactive or only_script:
166
        script_name = args.scriptname
167
        load(script_name, global_vars)
168
169
        if not only_script:
170
            enter_interactive_mode(global_vars)
171
172
    protocol.disconnect()
173
174
175
def enter_interactive_mode(global_vars):
176
    code.interact(
177
        banner='GVM Interactive Console. Type "help" to get information \
178
about functionality.',
179
        local=dict(global_vars))
180
181
182
def load(path, global_vars):
183
    """Loads a file into the interactive console
184
185
    Loads a file into the interactive console and execute it.
186
    TODO: Needs some security checks.
187
188
    Arguments:
189
        path {str} -- Path of file
190
    """
191
    try:
192
        file = open(path, 'r', newline='').read()
193
194
        exec(file, global_vars) # pylint: disable=exec-used
195
    except OSError as e:
196
        print(str(e))
197
198
199
if __name__ == '__main__':
200
    main()
201