Beispiel #1
0
 def __init__(self,
              host: Optional[str],
              port: int,
              ipvo: Optional[Sequence[int]] = None,
              timeout: Union[int, float] = 5,
              timeout_set: bool = False) -> None:
     super(SSH_Socket, self).__init__()
     self.__sock = None  # type: Optional[socket.socket]
     self.__sock_map = {}  # type: Dict[int, socket.socket]
     self.__block_size = 8
     self.__state = 0
     self.__header = []  # type: List[str]
     self.__banner = None  # type: Optional[Banner]
     if host is None:
         raise ValueError('undefined host')
     nport = Utils.parse_int(port)
     if nport < 1 or nport > 65535:
         raise ValueError('invalid port: {}'.format(port))
     self.__host = host
     self.__port = nport
     if ipvo is not None:
         self.__ipvo = ipvo
     else:
         self.__ipvo = ()
     self.__timeout = timeout
     self.__timeout_set = timeout_set
     self.client_host = None  # type: Optional[str]
     self.client_port = None
Beispiel #2
0
 def __init__(
     self,
     outputbuffer: 'OutputBuffer',
     host: Optional[str],
     port: int,
     ip_version_preference: List[int] = [],
     timeout: Union[int, float] = 5,
     timeout_set: bool = False
 ) -> None:  # pylint: disable=dangerous-default-value
     super(SSH_Socket, self).__init__()
     self.__outputbuffer = outputbuffer
     self.__sock: Optional[socket.socket] = None
     self.__sock_map: Dict[int, socket.socket] = {}
     self.__block_size = 8
     self.__state = 0
     self.__header: List[str] = []
     self.__banner: Optional[Banner] = None
     if host is None:
         raise ValueError('undefined host')
     nport = Utils.parse_int(port)
     if nport < 1 or nport > 65535:
         raise ValueError('invalid port: {}'.format(port))
     self.__host = host
     self.__port = nport
     self.__ip_version_preference = ip_version_preference  # Holds only 5 possible values: [] (no preference), [4] (use IPv4 only), [6] (use IPv6 only), [46] (use both IPv4 and IPv6, but prioritize v4), and [64] (use both IPv4 and IPv6, but prioritize v6).
     self.__timeout = timeout
     self.__timeout_set = timeout_set
     self.client_host: Optional[str] = None
     self.client_port = None
Beispiel #3
0
    def __setattr__(
            self, name: str, value: Union[str, int, float, bool,
                                          Sequence[int]]) -> None:
        valid = False
        if name in [
                'batch', 'client_audit', 'colors', 'json', 'list_policies',
                'manual', 'make_policy', 'ssh1', 'ssh2', 'timeout_set',
                'verbose', 'debug'
        ]:
            valid, value = True, bool(value)
        elif name in ['ipv4', 'ipv6']:
            valid, value = True, bool(value)
            if len(self.ip_version_preference
                   ) == 2:  # Being called more than twice is not valid.
                valid = False
            elif value:
                self.ip_version_preference.append(4 if name == 'ipv4' else 6)
        elif name == 'port':
            valid, port = True, Utils.parse_int(value)
            if port < 1 or port > 65535:
                raise ValueError('invalid port: {}'.format(value))
            value = port
        elif name in ['level']:
            if value not in ('info', 'warn', 'fail'):
                raise ValueError('invalid level: {}'.format(value))
            valid = True
        elif name == 'host':
            valid = True
        elif name == 'timeout':
            value = Utils.parse_float(value)
            if value == -1.0:
                raise ValueError('invalid timeout: {}'.format(value))
            valid = True
        elif name in [
                'ip_version_preference', 'lookup', 'policy_file', 'policy',
                'target_file', 'target_list'
        ]:
            valid = True
        elif name == "threads":
            valid, num_threads = True, Utils.parse_int(value)
            if num_threads < 1:
                raise ValueError('invalid number of threads: {}'.format(value))
            value = num_threads

        if valid:
            object.__setattr__(self, name, value)
Beispiel #4
0
    def __setattr__(
            self, name: str, value: Union[str, int, float, bool,
                                          Sequence[int]]) -> None:
        valid = False
        if name in [
                'ssh1', 'ssh2', 'batch', 'client_audit', 'colors', 'verbose',
                'timeout_set', 'json', 'make_policy', 'list_policies'
        ]:
            valid, value = True, bool(value)
        elif name in ['ipv4', 'ipv6']:
            valid = False
            value = bool(value)
            ipv = 4 if name == 'ipv4' else 6
            if value:
                value = tuple(list(self.ipvo) + [ipv])
            else:  # pylint: disable=else-if-used
                if len(self.ipvo) == 0:
                    value = (6, ) if ipv == 4 else (4, )
                else:
                    value = tuple([x for x in self.ipvo if x != ipv])
            self.__setattr__('ipvo', value)
        elif name == 'ipvo':
            if isinstance(value, (tuple, list)):
                uniq_value = Utils.unique_seq(value)
                value = tuple([x for x in uniq_value if x in (4, 6)])
                valid = True
                ipv_both = len(value) == 0
                object.__setattr__(self, 'ipv4', ipv_both or 4 in value)
                object.__setattr__(self, 'ipv6', ipv_both or 6 in value)
        elif name == 'port':
            valid, port = True, Utils.parse_int(value)
            if port < 1 or port > 65535:
                raise ValueError('invalid port: {}'.format(value))
            value = port
        elif name in ['level']:
            if value not in ('info', 'warn', 'fail'):
                raise ValueError('invalid level: {}'.format(value))
            valid = True
        elif name == 'host':
            valid = True
        elif name == 'timeout':
            value = Utils.parse_float(value)
            if value == -1.0:
                raise ValueError('invalid timeout: {}'.format(value))
            valid = True
        elif name in [
                'policy_file', 'policy', 'target_file', 'target_list', 'lookup'
        ]:
            valid = True

        if valid:
            object.__setattr__(self, name, value)
Beispiel #5
0
def process_commandline(out: OutputBuffer, args: List[str], usage_cb: Callable[..., None]) -> 'AuditConf':  # pylint: disable=too-many-statements
    # pylint: disable=too-many-branches
    aconf = AuditConf()
    try:
        sopts = 'h1246M:p:P:jbcnvl:t:T:Lmd'
        lopts = ['help', 'ssh1', 'ssh2', 'ipv4', 'ipv6', 'make-policy=', 'port=', 'policy=', 'json', 'batch', 'client-audit', 'no-colors', 'verbose', 'level=', 'timeout=', 'targets=', 'list-policies', 'lookup=', 'threads=', 'manual', 'debug']
        opts, args = getopt.gnu_getopt(args, sopts, lopts)
    except getopt.GetoptError as err:
        usage_cb(str(err))
    aconf.ssh1, aconf.ssh2 = False, False
    host: str = ''
    oport: Optional[str] = None
    port: int = 0
    for o, a in opts:
        if o in ('-h', '--help'):
            usage_cb()
        elif o in ('-1', '--ssh1'):
            aconf.ssh1 = True
        elif o in ('-2', '--ssh2'):
            aconf.ssh2 = True
        elif o in ('-4', '--ipv4'):
            aconf.ipv4 = True
        elif o in ('-6', '--ipv6'):
            aconf.ipv6 = True
        elif o in ('-p', '--port'):
            oport = a
        elif o in ('-b', '--batch'):
            aconf.batch = True
            aconf.verbose = True
        elif o in ('-c', '--client-audit'):
            aconf.client_audit = True
        elif o in ('-n', '--no-colors'):
            aconf.colors = False
            out.use_colors = False
        elif o in ('-j', '--json'):
            if aconf.json:  # If specified twice, enable indent printing.
                aconf.json_print_indent = True
            else:
                aconf.json = True
        elif o in ('-v', '--verbose'):
            aconf.verbose = True
            out.verbose = True
        elif o in ('-l', '--level'):
            if a not in ('info', 'warn', 'fail'):
                usage_cb('level {} is not valid'.format(a))
            aconf.level = a
        elif o in ('-t', '--timeout'):
            aconf.timeout = float(a)
            aconf.timeout_set = True
        elif o in ('-M', '--make-policy'):
            aconf.make_policy = True
            aconf.policy_file = a
        elif o in ('-P', '--policy'):
            aconf.policy_file = a
        elif o in ('-T', '--targets'):
            aconf.target_file = a
        elif o == '--threads':
            aconf.threads = int(a)
        elif o in ('-L', '--list-policies'):
            aconf.list_policies = True
        elif o == '--lookup':
            aconf.lookup = a
        elif o in ('-m', '--manual'):
            aconf.manual = True
        elif o in ('-d', '--debug'):
            aconf.debug = True
            out.debug = True

    if len(args) == 0 and aconf.client_audit is False and aconf.target_file is None and aconf.list_policies is False and aconf.lookup == '' and aconf.manual is False:
        usage_cb()

    if aconf.manual:
        return aconf

    if aconf.lookup != '':
        return aconf

    if aconf.list_policies:
        list_policies(out)
        sys.exit(exitcodes.GOOD)

    if aconf.client_audit is False and aconf.target_file is None:
        if oport is not None:
            host = args[0]
        else:
            host, port = Utils.parse_host_and_port(args[0])
        if not host and aconf.target_file is None:
            usage_cb('host is empty')

    if port == 0 and oport is None:
        if aconf.client_audit:  # The default port to listen on during a client audit is 2222.
            port = 2222
        else:
            port = 22

    if oport is not None:
        port = Utils.parse_int(oport)
        if port <= 0 or port > 65535:
            usage_cb('port {} is not valid'.format(oport))

    aconf.host = host
    aconf.port = port
    if not (aconf.ssh1 or aconf.ssh2):
        aconf.ssh1, aconf.ssh2 = True, True

    # If a file containing a list of targets was given, read it.
    if aconf.target_file is not None:
        try:
            with open(aconf.target_file, 'r', encoding='utf-8') as f:
                aconf.target_list = f.readlines()
        except PermissionError as e:
            # If installed as a Snap package, print a more useful message with potential work-arounds.
            if SNAP_PACKAGE:
                print(SNAP_PERMISSIONS_ERROR)
            else:
                print("Error: insufficient permissions: %s" % str(e))
            sys.exit(exitcodes.UNKNOWN_ERROR)

        # Strip out whitespace from each line in target file, and skip empty lines.
        aconf.target_list = [target.strip() for target in aconf.target_list if target not in ("", "\n")]

    # If a policy file was provided, validate it.
    if (aconf.policy_file is not None) and (aconf.make_policy is False):

        # First, see if this is a built-in policy name.  If not, assume a file path was provided, and try to load it from disk.
        aconf.policy = Policy.load_builtin_policy(aconf.policy_file)
        if aconf.policy is None:
            try:
                aconf.policy = Policy(policy_file=aconf.policy_file)
            except Exception as e:
                out.fail("Error while loading policy file: %s: %s" % (str(e), traceback.format_exc()))
                out.write()
                sys.exit(exitcodes.UNKNOWN_ERROR)

        # If the user wants to do a client audit, but provided a server policy, terminate.
        if aconf.client_audit and aconf.policy.is_server_policy():
            out.fail("Error: client audit selected, but server policy provided.")
            out.write()
            sys.exit(exitcodes.UNKNOWN_ERROR)

        # If the user wants to do a server audit, but provided a client policy, terminate.
        if aconf.client_audit is False and aconf.policy.is_server_policy() is False:
            out.fail("Error: server audit selected, but client policy provided.")
            out.write()
            sys.exit(exitcodes.UNKNOWN_ERROR)

    return aconf
Beispiel #6
0
def process_commandline(
    args: List[str], usage_cb: Callable[..., None]
) -> 'AuditConf':  # pylint: disable=too-many-statements
    # pylint: disable=too-many-branches
    aconf = AuditConf()
    try:
        sopts = 'h1246M:p:P:jbcnvl:t:T:L'
        lopts = [
            'help', 'ssh1', 'ssh2', 'ipv4', 'ipv6', 'make-policy=', 'port=',
            'policy=', 'json', 'batch', 'client-audit', 'no-colors', 'verbose',
            'level=', 'timeout=', 'targets=', 'list-policies', 'lookup='
        ]
        opts, args = getopt.gnu_getopt(args, sopts, lopts)
    except getopt.GetoptError as err:
        usage_cb(str(err))
    aconf.ssh1, aconf.ssh2 = False, False
    host = ''  # type: str
    oport = None  # type: Optional[str]
    port = 0  # type: int
    for o, a in opts:
        if o in ('-h', '--help'):
            usage_cb()
        elif o in ('-1', '--ssh1'):
            aconf.ssh1 = True
        elif o in ('-2', '--ssh2'):
            aconf.ssh2 = True
        elif o in ('-4', '--ipv4'):
            aconf.ipv4 = True
        elif o in ('-6', '--ipv6'):
            aconf.ipv6 = True
        elif o in ('-p', '--port'):
            oport = a
        elif o in ('-b', '--batch'):
            aconf.batch = True
            aconf.verbose = True
        elif o in ('-c', '--client-audit'):
            aconf.client_audit = True
        elif o in ('-n', '--no-colors'):
            aconf.colors = False
        elif o in ('-j', '--json'):
            aconf.json = True
        elif o in ('-v', '--verbose'):
            aconf.verbose = True
        elif o in ('-l', '--level'):
            if a not in ('info', 'warn', 'fail'):
                usage_cb('level {} is not valid'.format(a))
            aconf.level = a
        elif o in ('-t', '--timeout'):
            aconf.timeout = float(a)
            aconf.timeout_set = True
        elif o in ('-M', '--make-policy'):
            aconf.make_policy = True
            aconf.policy_file = a
        elif o in ('-P', '--policy'):
            aconf.policy_file = a
        elif o in ('-T', '--targets'):
            aconf.target_file = a
        elif o in ('-L', '--list-policies'):
            aconf.list_policies = True
        elif o == '--lookup':
            aconf.lookup = a

    if len(
            args
    ) == 0 and aconf.client_audit is False and aconf.target_file is None and aconf.list_policies is False and aconf.lookup == '':
        usage_cb()

    if aconf.lookup != '':
        return aconf

    if aconf.list_policies:
        list_policies()
        sys.exit(exitcodes.GOOD)

    if aconf.client_audit is False and aconf.target_file is None:
        if oport is not None:
            host = args[0]
        else:
            host, port = Utils.parse_host_and_port(args[0])
        if not host and aconf.target_file is None:
            usage_cb('host is empty')

    if port == 0 and oport is None:
        if aconf.client_audit:  # The default port to listen on during a client audit is 2222.
            port = 2222
        else:
            port = 22

    if oport is not None:
        port = Utils.parse_int(oport)
        if port <= 0 or port > 65535:
            usage_cb('port {} is not valid'.format(oport))

    aconf.host = host
    aconf.port = port
    if not (aconf.ssh1 or aconf.ssh2):
        aconf.ssh1, aconf.ssh2 = True, True

    # If a file containing a list of targets was given, read it.
    if aconf.target_file is not None:
        with open(aconf.target_file, 'r') as f:
            aconf.target_list = f.readlines()

        # Strip out whitespace from each line in target file, and skip empty lines.
        aconf.target_list = [
            target.strip() for target in aconf.target_list
            if target not in ("", "\n")
        ]

    # If a policy file was provided, validate it.
    if (aconf.policy_file is not None) and (aconf.make_policy is False):
        try:
            aconf.policy = Policy(policy_file=aconf.policy_file)
        except Exception as e:
            print("Error while loading policy file: %s: %s" %
                  (str(e), traceback.format_exc()))
            sys.exit(exitcodes.UNKNOWN_ERROR)

        # If the user wants to do a client audit, but provided a server policy, terminate.
        if aconf.client_audit and aconf.policy.is_server_policy():
            print("Error: client audit selected, but server policy provided.")
            sys.exit(exitcodes.UNKNOWN_ERROR)

        # If the user wants to do a server audit, but provided a client policy, terminate.
        if aconf.client_audit is False and aconf.policy.is_server_policy(
        ) is False:
            print("Error: server audit selected, but client policy provided.")
            sys.exit(exitcodes.UNKNOWN_ERROR)

    return aconf