Beispiel #1
0
    def fetch_condensed_graph(self, msg):
        """ Return JSON for the nodes and links of the raw policy rules.
        This is a condensed format where <subject> and <object>.<class>
        are nodes, and permissions are links between them.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        #del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol
        	and 'parameterized' in refpol['parsed']
        	and 'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached condensed graph JSON")
        else:
            # Parse the policy
            ws_domains.call('raw', 'parse', msg)
            # Read the policy again
            refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if (not 'condensed' in refpol['parsed']['parameterized']):

            # Build the node and link lists from the rules table
            rules = refpol['parsed']['parameterized']['rules']
            node_map = {}
            link_map = {}
            node_list = []
            link_list = []
            RawDomain.condensedNodesFromRules(rules, node_map, link_map, node_list, link_list)

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)

            refpol['parsed']['parameterized']['condensed'] = {
            	'nodes': node_list,
            	'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or raw to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('raw', None)
        refpol['parsed']['parameterized'].pop('condensed_lobster', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #2
0
    def fetch_raw_graph(self, msg):
        """ Return JSON for the nodes and links of the raw policy rules.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        #del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol
        	and 'parameterized' in refpol['parsed']
        	and'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")
        else:
            # Parse the policy
            ws_domains.call('raw', 'parse', msg)
            # Read the policy again
            refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if (not 'raw' in refpol['parsed']['parameterized']):

            # Build the node and link lists from the rules table
            rules = refpol['parsed']['parameterized']['rules']
            node_map = {} # Maps a node name to its list index
            link_map = {} # Maps a link name to its list index
            node_list = [] # List of nodes
            link_list = [] # List of links
            RawDomain.nodesFromRules(rules, refpol.id, node_map, link_map, node_list, link_list)
            for node in node_list:
            	node['l'] = list(node['l'])

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)

            refpol['parsed']['parameterized']['raw'] = {
            	'nodes': node_list,
            	'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or condensed graph to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('condensed', None)
        refpol['parsed']['parameterized'].pop('condensed_lobster', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #3
0
    def fetch_condensed_graph(self, msg):
        """ Return JSON for the nodes and links of the raw policy rules.
        This is a condensed format where <subject> and <object>.<class>
        are nodes, and permissions are links between them.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        #del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol and 'parameterized' in refpol['parsed']
                and 'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached condensed graph JSON")
        else:
            # Parse the policy
            ws_domains.call('raw', 'parse', msg)
            # Read the policy again
            refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if (not 'condensed' in refpol['parsed']['parameterized']):

            # Build the node and link lists from the rules table
            rules = refpol['parsed']['parameterized']['rules']
            node_map = {}
            link_map = {}
            node_list = []
            link_list = []
            RawDomain.condensedNodesFromRules(rules, node_map, link_map,
                                              node_list, link_list)

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)

            refpol['parsed']['parameterized']['condensed'] = {
                'nodes': node_list,
                'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or raw to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('raw', None)
        refpol['parsed']['parameterized'].pop('condensed_lobster', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #4
0
    def fetch_raw_graph(self, msg):
        """ Return JSON for the nodes and links of the raw policy rules.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        #del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol and 'parameterized' in refpol['parsed']
                and 'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")
        else:
            # Parse the policy
            ws_domains.call('raw', 'parse', msg)
            # Read the policy again
            refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if (not 'raw' in refpol['parsed']['parameterized']):

            # Build the node and link lists from the rules table
            rules = refpol['parsed']['parameterized']['rules']
            node_map = {}  # Maps a node name to its list index
            link_map = {}  # Maps a link name to its list index
            node_list = []  # List of nodes
            link_list = []  # List of links
            RawDomain.nodesFromRules(rules, refpol.id, node_map, link_map,
                                     node_list, link_list)
            for node in node_list:
                node['l'] = list(node['l'])

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)

            refpol['parsed']['parameterized']['raw'] = {
                'nodes': node_list,
                'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or condensed graph to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('condensed', None)
        refpol['parsed']['parameterized'].pop('condensed_lobster', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #5
0
    def get(self, filetype):
      import api.handlers.ws_domains as ws_domains
      self.set_header('Cache-control', 'no-cache')

      identifier = self.get_argument('id', None)

      if filetype == 'refpolicy':
        if identifier is None:
          self.clear()
          self.set_status(400)
          self.finish("Missing required parameter: id")
          return

        # Check the identifier.
        try:
          identifier = api.db.idtype(identifier)
        except bson.errors.InvalidId:
          self.clear()
          self.set_status(404)
          self.finish("Could not find policy: {0}".format(identifier))

        refpolicy = ws_domains.call('refpolicy', 'Read', identifier)
        if not refpolicy:
          self.clear()
          self.set_status(404)
          self.finish("Could not find policy: {0}".format(identifier))
          return

        selinux = ws_domains.call(
            'lobster',
            'export_selinux',
            refpolicy.documents['dsl']['text']
        )

        self.set_header(
            'Content-Type', 'text/plain')

        self.set_header(
            'Content-Length', len(selinux))

        self.set_header(
            'Content-Disposition',
            'attachment;filename={fname};size={length}'
            .format(fname=refpolicy.id, length=len(selinux)))

        self.finish(selinux)
      else:
        self.clear()
        self.set_status(400)
        self.finish("Unrecognized filetype: {0}".format(filetype))
Beispiel #6
0
    def parse(self, msg):
        """ Return the JSON graph for the given policy. Params of the form

            {
              "payload":
                {
                    "policy": "policyid"
                }
            }
        """
        logger.info("Params: {0}".format(msg))

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol
            and 'parameterized' in refpol['parsed']
            and 'lobster_rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")

        else:

            dsl_json = refpol['documents']['dsl']['text']

        # Return the cached version if available

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #7
0
    def parse(self, msg):
        """ Return the JSON graph for the given policy. Params of the form

            {
              "payload":
                {
                    "policy": "policyid"
                }
            }
        """
        logger.info("Params: {0}".format(msg))

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol and 'parameterized' in refpol['parsed']
                and 'lobster_rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")

        else:

            dsl_json = refpol['documents']['dsl']['text']

        # Return the cached version if available

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #8
0
    def get(self, filetype):
        import api.handlers.ws_domains as ws_domains
        self.set_header('Cache-control', 'no-cache')

        identifier = self.get_argument('id', None)

        if filetype == 'refpolicy':
            if identifier is None:
                self.clear()
                self.set_status(400)
                self.finish("Missing required parameter: id")
                return

            # Check the identifier.
            try:
                identifier = api.db.idtype(identifier)
            except bson.errors.InvalidId:
                self.clear()
                self.set_status(404)
                self.finish("Could not find policy: {0}".format(identifier))

            refpolicy = ws_domains.call('refpolicy', 'Read', identifier)
            if not refpolicy:
                self.clear()
                self.set_status(404)
                self.finish("Could not find policy: {0}".format(identifier))
                return

            selinux = ws_domains.call('lobster', 'export_selinux',
                                      refpolicy.documents['dsl']['text'])

            self.set_header('Content-Type', 'text/plain')

            self.set_header('Content-Length', len(selinux))

            self.set_header(
                'Content-Disposition',
                'attachment;filename={fname};size={length}'.format(
                    fname=refpolicy.id, length=len(selinux)))

            self.finish(selinux)
        else:
            self.clear()
            self.set_status(400)
            self.finish("Unrecognized filetype: {0}".format(filetype))
Beispiel #9
0
    def query_reachability(self, msg):
        """ Run a reachability test from a given domain """
        logger.info("WS:query_reachability?%s" % msg['payload']['params'])

        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']
        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        output = self._make_request(
            'POST', '/paths?{0}'.format(msg['payload']['params']),
            msg['payload']['text'])

        result = api.db.json.loads(output.body)['result']

        if result is not None:
            for dest, paths in result.iteritems():
                if dest == 'truncated':
                    continue

                new_paths = {'dest_id': dest, 'perms': {}}
                for path in paths:
                    logger.info(
                        'Gathering additional data for {0}'.format(path))
                    import urlparse
                    params = urlparse.parse_qs(msg['payload']['params'])

                    path_data, final_perm = self.path_walk(
                        path, refpol.parsed, params['id'][0],
                        msg['payload']['text'])

                    logger.info("Re-tabulated path data")

                    new_paths['dest'] = path_data[-1]['name']
                    for klass, perm in final_perm['name']:
                        new_paths['perms'][perm] = {
                            'hops': path,
                            'human': path_data,
                            'perm': perm,
                            'class': klass,
                            'endpoint': path_data[-1]
                        }

                result[dest] = new_paths

        return {
            'label': msg['response_id'],
            'payload': {
                'paths': result,
                'data': refpol.parsed
            }
        }
Beispiel #10
0
    def query_reachability(self, msg):
        """ Run a reachability test from a given domain """
        logger.info("WS:query_reachability?%s" % msg['payload']['params'])

        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']
        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        output = self._make_request(
            'POST', '/paths?{0}'.format(msg['payload']['params']),
            msg['payload']['text'])

        result = api.db.json.loads(output.body)['result']

        if result is not None:
          for dest, paths in result.iteritems():
              if dest == 'truncated':
                  continue

              new_paths = {'dest_id': dest, 'perms': {}}
              for path in paths:
                  logger.info('Gathering additional data for {0}'.format(path))
                  import urlparse
                  params = urlparse.parse_qs(msg['payload']['params'])

                  path_data, final_perm = self.path_walk(
                      path,
                      refpol.parsed,
                      params['id'][0],
                      msg['payload']['text'])

                  logger.info("Re-tabulated path data")

                  new_paths['dest'] = path_data[-1]['name']
                  for klass, perm in final_perm['name']:
                      new_paths['perms'][perm] = {
                          'hops': path,
                          'human': path_data,
                          'perm': perm,
                          'class': klass,
                          'endpoint': path_data[-1]
                      }

              result[dest] = new_paths

        return {
            'label': msg['response_id'],
            'payload': {'paths': result, 'data': refpol.parsed}
        }
Beispiel #11
0
def get_dsl_for_policy(refpol, dynamic_policy):
    """ Get the web service to tranlate the provided policy (with associated
    refpolicy) into the Lobster DSL """

    translate_args = {
        'refpolicy': refpol.id,
        'modules': []
    }

    if dynamic_policy['modified'] is True:
        # If None, it means this module has not be modified
        translate_args['modules'].append({
            'name': dynamic_policy.id,
            'if': dynamic_policy['documents']
            .get('if', {}).get('text', ""),
            'te': dynamic_policy['documents']
            .get('te', {}).get('text', ""),
            'fc': dynamic_policy['documents']
            .get('fc', {}).get('text', "")
        })

    dsl = ws_domains.call(
        'lobster',
        'translate_selinux',
        translate_args)

    if len(dsl['errors']) > 0:
      raise Exception("Failed to translate DSL: {0}"
                      .format("\n".join(
                          ("{0}".format(x) for x in dsl['errors']))))

    dynamic_policy['documents']['dsl'] = {
        'text': dsl['result'],
        'mode': 'lobster'
    }

    dynamic_policy.Insert()
Beispiel #12
0
    def validate(self, msg):
        """ Validate a Lobster file received from the IDE
        """
        dsl = msg['payload']['text']
        del msg['payload']['text']
        dsl_hash = hashlib.md5(dsl).hexdigest()

        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        logger.info("WS:validate?%s" % "&".join(
            ["{0}={1}".format(x, y) for x, y in msg['payload'].iteritems() if x != 'text']))

        # If the DSL is identical, and the parameters are identical, just return the one we already
        # translated.
        if (refpol.parsed
                and refpol.documents['dsl']['digest'] == dsl_hash
                and refpol.parsed['params'] == msg['payload']['params']):

            logger.info("Returning cached JSON")

            return {
                'label': msg['response_id'],
                'payload': api.db.json.dumps(refpol.parsed)
            }

        else:

            output = self._make_request(
                'POST', '/parse?{0}'.format(msg['payload']['params']),
                dsl)

            jsondata = api.db.json.loads(output.body)
            if msg['payload']['hide_unused_ports'] is True:
                jsondata = self._filter_unused_ports(jsondata)

            refpol['parsed'] = {
                'version': jsondata['version'],
                'errors': jsondata['errors'],
                'parameterized': jsondata['result'],
                'params': msg['payload']['params']
            }

            # If this DSL is different, then we need to recalculate the 
            # summarized version, which is parsed with paths=*
            if (len(jsondata['errors']) == 0
              and 'summary' not in refpol.parsed
              or refpol.documents['dsl']['digest'] != dsl_hash):
                output = self._make_request( 'POST', '/parse?path=*', dsl)
                jsondata = api.db.json.loads(output.body)
                refpol.parsed['full'] = jsondata['result']
                if jsondata['result'] is not None:
                  refpol.parsed['summary'] = api.support.decompose.flatten_perms(jsondata['result'])
                  refpol.parsed['permset'] = [{'text': x, "id": x}
                                              for x
                                              in api.support.decompose.perm_set(
                                                jsondata['result'])]
                else:
                  refpol.parsed['summary'] = []
                  refpol.parsed['permset'] = []


            refpol.Insert()

        del refpol.parsed['full']
        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #13
0
    def fetch_graph(self, msg):
        """ Return the JSON graph for the given policy. Params of the form

            {
              "payload":
                {
                    "policy": "policyid"
                }
            }
        """
        logger.info("Params: {0}".format(msg))

        # Assume we have already run translate_selinux() during policy upload

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if ('parsed' not in refpol or 'parameterized' not in refpol['parsed']
                or 'condensed_lobster'
                not in refpol['parsed']['parameterized']):

            lobster_json = api.db.json.loads(
                refpol['documents']['dsl']['text'])
            lobster_json = lobster_json['result']

            connections = lobster_json['connections']
            ports = lobster_json['ports']
            domains = lobster_json['domains']

            node_map = {}
            link_map = {}
            module_map = {}
            node_list = []
            link_list = []
            module_list = []
            for key in connections.keys():
                conn = connections[key]
                te_file = ""
                perm_list = []

                left_dom = domains[conn['left_dom']]
                right_dom = domains[conn['right_dom']]

                left_port = ports[conn['left']]
                right_port = ports[conn['right']]

                active_dom = left_dom
                inactive_dom = right_dom
                if right_port['name'] == 'active':
                    active_dom = right_dom
                    inactive_dom = left_dom

                for annot in conn['annotations']:
                    if annot['name'] == 'Perm':
                        perm_list.append(annot['args'])  # [class, perm]
                    elif annot['name'] == 'SourcePos':
                        te_file = annot['args'][0]

                # Skip connections that do not have any permissions
                if len(perm_list) == 0:
                    continue

                # Skip this connection if one of the domains is not an Attribute or a Type
                bothAreTypesOrAttrs = True
                for dom in [left_dom, right_dom]:
                    validAnnots = []
                    for domAnnot in dom['domainAnnotations']:
                        if domAnnot['name'] == 'Attribute' or domAnnot[
                                'name'] == 'Type':
                            validAnnots.append(domAnnot)
                    if len(validAnnots) == 0:
                        bothAreTypesOrAttrs = bothAreTypesOrAttrs and False

                if not bothAreTypesOrAttrs:
                    continue

                mod_idx = module_map.get(active_dom['module'], -1)
                if (mod_idx == -1):
                    mod_idx = len(module_list)
                    module_map[active_dom['module']] = mod_idx
                    module_list.append(active_dom['module'])

                # Create/get the source node
                source_key = active_dom['name']
                source_idx = node_map.get(source_key, -1)
                if source_idx == -1:
                    source_node = {'n': source_key, 'm': mod_idx}
                    source_idx = len(node_list)
                    node_map[source_key] = source_idx
                    node_list.append(source_node)

                # Loop over each class to create the object.class pairs
                for perm in perm_list:
                    mod_idx = module_map.get(inactive_dom['module'], -1)
                    if (mod_idx == -1):
                        mod_idx = len(module_list)
                        module_map[inactive_dom['module']] = mod_idx
                        module_list.append(inactive_dom['module'])

                    target_key = inactive_dom['name'] + '.' + perm[0]
                    target_idx = node_map.get(target_key, -1)
                    if target_idx == -1:
                        target_node = {'n': target_key, 'm': mod_idx}
                        target_idx = len(node_list)
                        node_map[target_key] = target_idx
                        node_list.append(target_node)
                    link_key = source_key + '-' + target_key
                    link = link_map.get(link_key, -1)
                    if link == -1:
                        link = {
                            's': source_idx,
                            't': target_idx,
                            'p': [perm[1]]
                        }
                        link_map[link_key] = link
                        link_list.append(link)
                    elif perm[1] not in link['p']:
                        link['p'].append(perm[1])

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)
            module_list = module_list

            if 'parsed' not in refpol:
                refpol['parsed'] = {
                    'version': '1.0',
                    'errors': [],
                    'parameterized': {}
                }

            refpol['parsed']['parameterized']['condensed_lobster'] = {
                'modules': module_list,
                'nodes': node_list,
                'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or raw to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('raw', None)
        refpol['parsed']['parameterized'].pop('condensed', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }

        # Return the cached version if available

        return api.db.json.loads({})
Beispiel #14
0
    def validate(self, msg):
        """ Validate a Lobster file received from the IDE
        """
        dsl = msg['payload']['text']
        del msg['payload']['text']
        dsl_hash = hashlib.md5(dsl).hexdigest()

        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        logger.info("WS:validate?%s" % "&".join([
            "{0}={1}".format(x, y)
            for x, y in msg['payload'].iteritems() if x != 'text'
        ]))

        # If the DSL is identical, and the parameters are identical, just return the one we already
        # translated.
        if (refpol.parsed and refpol.documents['dsl']['digest'] == dsl_hash
                and refpol.parsed['params'] == msg['payload']['params']):

            logger.info("Returning cached JSON")

            return {
                'label': msg['response_id'],
                'payload': api.db.json.dumps(refpol.parsed)
            }

        else:

            output = self._make_request(
                'POST', '/parse?{0}'.format(msg['payload']['params']), dsl)

            jsondata = api.db.json.loads(output.body)
            if msg['payload']['hide_unused_ports'] is True:
                jsondata = self._filter_unused_ports(jsondata)

            refpol['parsed'] = {
                'version': jsondata['version'],
                'errors': jsondata['errors'],
                'parameterized': jsondata['result'],
                'params': msg['payload']['params']
            }

            # If this DSL is different, then we need to recalculate the
            # summarized version, which is parsed with paths=*
            if (len(jsondata['errors']) == 0 and 'summary' not in refpol.parsed
                    or refpol.documents['dsl']['digest'] != dsl_hash):
                output = self._make_request('POST', '/parse?path=*', dsl)
                jsondata = api.db.json.loads(output.body)
                refpol.parsed['full'] = jsondata['result']
                if jsondata['result'] is not None:
                    refpol.parsed[
                        'summary'] = api.support.decompose.flatten_perms(
                            jsondata['result'])
                    refpol.parsed['permset'] = [{
                        'text': x,
                        "id": x
                    } for x in api.support.decompose.perm_set(
                        jsondata['result'])]
                else:
                    refpol.parsed['summary'] = []
                    refpol.parsed['permset'] = []

            refpol.Insert()

        del refpol.parsed['full']
        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #15
0
    def parse(self, msg):
        """ Given a set of parameters of the form, return the
        JSON for the raw module.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol
        	and 'parameterized' in refpol['parsed']
        	and 'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")

        else:

            raw = refpol['documents']['raw']['text']

            table = []

            # Need to get the parsed data for all the modules
            # Use ws_domains.call() to invoke raw.py and get the raw policy
            line_num = 0
            logger.info("Parsing {0} rule lines".format(len(raw.splitlines())))
            for line in raw.splitlines():
                line_num += 1
                # Split on ":"
                rule = line.strip().split(":")

                lside = rule[0].lstrip("allow").strip()
                rside = rule[1].strip()

                if lside.find("{") == -1:
                    # Should be "subj_t obj_t;"
                    subj_t = lside.split(" ")[0]
                    obj_t = lside.split(" ")[1]
                elif lside.find("{") < lside.find(" "):
                    # We have a list of subjects
                    subj_t = lside[lside.find("{")+1:lside.find("}")].strip()
                    if lside.find("}") == lside.rfind("}"):
                        # {subj_t1 subj_t2} obj_t;
                        obj_t = lside.split("}")[1].rstrip(";").strip()
                    else:
                        # {subj_t1 subj_t2} {obj_t1 obj_t2};
                        obj_t = lside[lside.rfind("{")+1:lside.rfind("}")].strip()
                else:
                    # subj_t {obj_t1 obj_t2};
                    subj_t = lside.split("{")[0].strip()
                    obj_t = lside[lside.find("{")+1:lside.find("}")].strip()

                if rside.find("{") == -1:
                    # Should be "obj_c perm;"
                    obj_c = rside.split(" ")[0]
                    perms = rside.split(" ")[1].rstrip(";")
                elif rside.find("{") < rside.find(" "):
                    # We have a list of classes
                    obj_c = rside[rside.find("{")+1:rside.find("}")].strip()
                    if rside.find("}") == rside.rfind("}"):
                        # {obj_c1 obj_c2} permission;
                        perms = rside.split("}")[1].rstrip(";").strip()
                    else:
                        # {obj_c1 obj_c2} {perm1 perm2};
                        perms = rside[rside.rfind("{")+1:rside.rfind("}")].strip()
                else:
                    # obj_c {perm1 perm2};
                    obj_c = rside.split("{")[0].strip()
                    perms = rside[rside.find("{")+1:rside.find("}")].strip()

                for s in subj_t.split(" "):
                    for ot in obj_t.split(" "):
                        for oc in obj_c.split(" "):
                            for p in perms.split(" "):
                                row = {"subject":s, "object":ot, "class":oc, "perm":p, "rule": line.strip()}
                                table.append(row)

            if 'parsed' not in refpol:
                refpol['parsed'] = {
                    'version': '1.0',
                    'errors': [],
                    'parameterized': {}
                }

            if 'parameterized' not in refpol['parsed']:
            	refpol['parsed']['parameterized'] = {}

            refpol['parsed']['parameterized']['rules'] = table

            refpol.Insert()

        # Don't send the rules to the client
        refpol['parsed']['parameterized'].pop('rules', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #16
0
    def fetch_graph(self, msg):
        """ Return the JSON graph for the given policy. Params of the form

            {
              "payload":
                {
                    "policy": "policyid"
                }
            }
        """
        logger.info("Params: {0}".format(msg))

        # Assume we have already run translate_selinux() during policy upload

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        if ('parsed' not in refpol or 'parameterized' not in refpol['parsed']
            or 'condensed_lobster' not in refpol['parsed']['parameterized']):

            lobster_json = api.db.json.loads(refpol['documents']['dsl']['text'])
            lobster_json = lobster_json['result']

            connections = lobster_json['connections']
            ports = lobster_json['ports']
            domains = lobster_json['domains']

            node_map = {}
            link_map = {}
            module_map = {}
            node_list = []
            link_list = []
            module_list = []
            for key in connections.keys():
                conn = connections[key]
                te_file = ""
                perm_list = []

                left_dom = domains[conn['left_dom']]
                right_dom = domains[conn['right_dom']]

                left_port = ports[conn['left']]
                right_port = ports[conn['right']]

                active_dom = left_dom
                inactive_dom = right_dom
                if right_port['name'] == 'active':
                    active_dom = right_dom
                    inactive_dom = left_dom

                for annot in conn['annotations']:
                    if annot['name'] == 'Perm':
                        perm_list.append(annot['args']) # [class, perm]
                    elif annot['name'] == 'SourcePos':
                        te_file = annot['args'][0]

                # Skip connections that do not have any permissions
                if len(perm_list) == 0:
                    continue

                # Skip this connection if one of the domains is not an Attribute or a Type
                bothAreTypesOrAttrs = True
                for dom in [left_dom, right_dom]:
                    validAnnots = []
                    for domAnnot in dom['domainAnnotations']:
                        if domAnnot['name'] == 'Attribute' or domAnnot['name'] == 'Type':
                            validAnnots.append(domAnnot)
                    if len(validAnnots) == 0:
                        bothAreTypesOrAttrs = bothAreTypesOrAttrs and False

                if not bothAreTypesOrAttrs:
                    continue

                mod_idx = module_map.get(active_dom['module'], -1)
                if (mod_idx == -1):
                    mod_idx = len(module_list)
                    module_map[active_dom['module']] = mod_idx
                    module_list.append(active_dom['module'])

                # Create/get the source node
                source_key = active_dom['name']
                source_idx = node_map.get(source_key, -1)
                if source_idx == -1:
                    source_node = { 'n': source_key, 'm': mod_idx }
                    source_idx = len(node_list)
                    node_map[source_key] = source_idx
                    node_list.append(source_node)

                # Loop over each class to create the object.class pairs
                for perm in perm_list:
                    mod_idx = module_map.get(inactive_dom['module'], -1)
                    if (mod_idx == -1):
                        mod_idx = len(module_list)
                        module_map[inactive_dom['module']] = mod_idx
                        module_list.append(inactive_dom['module'])

                    target_key = inactive_dom['name'] + '.' + perm[0]
                    target_idx = node_map.get(target_key, -1)
                    if target_idx == -1:
                        target_node = { 'n': target_key, 'm': mod_idx }
                        target_idx = len(node_list)
                        node_map[target_key] = target_idx
                        node_list.append(target_node)
                    link_key = source_key + '-' + target_key
                    link = link_map.get(link_key, -1)
                    if link == -1:
                        link = {
                            's': source_idx,
                            't': target_idx,
                            'p': [perm[1]]
                        }
                        link_map[link_key] = link
                        link_list.append(link)
                    elif perm[1] not in link['p']:
                        link['p'].append(perm[1])

            # Sparsify/compress the dicts/JSON objects
            node_list = api.jsonh.dumps(node_list)
            link_list = api.jsonh.dumps(link_list)
            module_list = module_list

            if 'parsed' not in refpol:
                refpol['parsed'] = {
                    'version': '1.0',
                    'errors': [],
                    'parameterized': {}
                }

            refpol['parsed']['parameterized']['condensed_lobster'] = {
                'modules': module_list,
                'nodes': node_list,
                'links': link_list
            }

            refpol.Insert()

        # Don't send the rules or raw to the client
        refpol['parsed']['parameterized'].pop('rules', None)
        refpol['parsed']['parameterized'].pop('raw', None)
        refpol['parsed']['parameterized'].pop('condensed', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }

        # Return the cached version if available

        return api.db.json.loads({})
Beispiel #17
0
    def do_upload_chunk(cls, params, response):
        # Make sure the directory exists
        try:
            os.makedirs(
                os.path.join(api.config.get('storage', 'bulk_storage_dir'),
                             'tmp'))
        except:
            pass

        name = params['name'][:-4] if params['name'].endswith(
            '.zip') else params['name']

        name = os.path.basename(name)  # be a little safer
        if not name:
            raise Exception("Invalid name for policy.")

        metadata = cls.Read({'id': name})

        if metadata is None:
            metadata = cls({
                'id':
                name,
                'written':
                params['index'],
                'total':
                params['total'],
                'tmpfile':
                os.path.join(api.config.get('storage', 'bulk_storage_dir'),
                             "tmp", params['name'])
            })

        elif 'tmpfile' not in metadata and 'disk_location' in metadata:
            raise Exception('Policy already exists')
        elif metadata['written'] < params['index']:
            os.remove(metadata['tmpfile'])
            metadata.Delete()
            raise Exception("Received out-of-order chunk. "
                            "Expected {0}. Got {1}".format(
                                metadata['written'], params['index']))

        metadata['written'] = params['index']

        mode = 'r+b' if os.path.exists(metadata['tmpfile']) else 'wb'

        with open(metadata['tmpfile'], mode) as fout:
            fout.seek(params['index'])
            raw_data = base64.b64decode(params['data'])
            fout.write(raw_data)
            fout.flush()

        metadata['written'] += params['length']
        if metadata['written'] == metadata['total']:
            try:
                metadata.extract_zipped_policy()
                module_info = metadata.read_policy_modules()
                sesearch_result = metadata.parse_policy_binary()

                errors = []

                supported_docs = {'dsl': False, 'raw': False}

                # Do we have source rules?
                if len(module_info['error']) > 0:
                    errors.append(module_info['error'])
                else:
                    supported_docs['dsl'] = True

                # Do we have the binary rules?
                if len(sesearch_result['error']) > 0:
                    errors.append(sesearch_result['error'])
                else:
                    supported_docs['raw'] = True

                if not supported_docs['dsl'] and not supported_docs['raw']:
                    raise api.DisplayError(
                        "Cannot find binary policy or reference policy source in the zip file"
                    )

                if supported_docs['dsl'] is True:
                    # Import the policy into Lobster
                    lobster_import = {'refpolicy': metadata.id, 'modules': []}

                    lobster_json = ws_domains.call('lobster',
                                                   'translate_selinux',
                                                   lobster_import)

                    # TODO check the results['error'] array to see if problems

                    metadata['documents'] = {
                        'dsl': {
                            'text': lobster_json,
                            'mode': 'dsl',
                            'digest': hashlib.md5(lobster_json).hexdigest(
                            )  #hashlib.md5(api.db.json.dumps(lobster_json['result'])).hexdigest()
                        }
                    }

                metadata['supported_docs'] = supported_docs

                metadata['modules'] = module_info['data']

                if 'documents' not in metadata:
                    metadata['documents'] = {}
                metadata['documents']['raw'] = {
                    'text': sesearch_result['data'],
                    'mode': 'raw',
                    'digest': hashlib.md5(sesearch_result['data']).hexdigest()
                }
            except Exception:
                metadata.Delete()
                raise
            else:
                metadata['valid'] = True

        metadata.Insert()

        response['payload'] = {
            'progress': float(metadata['written']) / float(metadata['total']),
            'info': {
                '_id': metadata['_id'],
                'id': metadata['id']
            }
        }

        return response
Beispiel #18
0
    def parse(self, msg):
        """ Given a set of parameters of the form, return the
        JSON for the raw module.
        """

        # msg.payload.policy is the id
        refpol_id = msg['payload']['policy']
        del msg['payload']['policy']

        refpol_id = api.db.idtype(refpol_id)
        refpol = ws_domains.call('refpolicy', 'Read', refpol_id)

        # If already parsed, just return the one we already translated.
        if ('parsed' in refpol and 'parameterized' in refpol['parsed']
                and 'rules' in refpol['parsed']['parameterized']):
            logger.info("Returning cached JSON")

        else:

            raw = refpol['documents']['raw']['text']

            table = []

            # Need to get the parsed data for all the modules
            # Use ws_domains.call() to invoke raw.py and get the raw policy
            line_num = 0
            logger.info("Parsing {0} rule lines".format(len(raw.splitlines())))
            for line in raw.splitlines():
                line_num += 1
                # Split on ":"
                rule = line.strip().split(":")

                lside = rule[0].lstrip("allow").strip()
                rside = rule[1].strip()

                if lside.find("{") == -1:
                    # Should be "subj_t obj_t;"
                    subj_t = lside.split(" ")[0]
                    obj_t = lside.split(" ")[1]
                elif lside.find("{") < lside.find(" "):
                    # We have a list of subjects
                    subj_t = lside[lside.find("{") + 1:lside.find("}")].strip()
                    if lside.find("}") == lside.rfind("}"):
                        # {subj_t1 subj_t2} obj_t;
                        obj_t = lside.split("}")[1].rstrip(";").strip()
                    else:
                        # {subj_t1 subj_t2} {obj_t1 obj_t2};
                        obj_t = lside[lside.rfind("{") +
                                      1:lside.rfind("}")].strip()
                else:
                    # subj_t {obj_t1 obj_t2};
                    subj_t = lside.split("{")[0].strip()
                    obj_t = lside[lside.find("{") + 1:lside.find("}")].strip()

                if rside.find("{") == -1:
                    # Should be "obj_c perm;"
                    obj_c = rside.split(" ")[0]
                    perms = rside.split(" ")[1].rstrip(";")
                elif rside.find("{") < rside.find(" "):
                    # We have a list of classes
                    obj_c = rside[rside.find("{") + 1:rside.find("}")].strip()
                    if rside.find("}") == rside.rfind("}"):
                        # {obj_c1 obj_c2} permission;
                        perms = rside.split("}")[1].rstrip(";").strip()
                    else:
                        # {obj_c1 obj_c2} {perm1 perm2};
                        perms = rside[rside.rfind("{") +
                                      1:rside.rfind("}")].strip()
                else:
                    # obj_c {perm1 perm2};
                    obj_c = rside.split("{")[0].strip()
                    perms = rside[rside.find("{") + 1:rside.find("}")].strip()

                for s in subj_t.split(" "):
                    for ot in obj_t.split(" "):
                        for oc in obj_c.split(" "):
                            for p in perms.split(" "):
                                row = {
                                    "subject": s,
                                    "object": ot,
                                    "class": oc,
                                    "perm": p,
                                    "rule": line.strip()
                                }
                                table.append(row)

            if 'parsed' not in refpol:
                refpol['parsed'] = {
                    'version': '1.0',
                    'errors': [],
                    'parameterized': {}
                }

            if 'parameterized' not in refpol['parsed']:
                refpol['parsed']['parameterized'] = {}

            refpol['parsed']['parameterized']['rules'] = table

            refpol.Insert()

        # Don't send the rules to the client
        refpol['parsed']['parameterized'].pop('rules', None)

        return {
            'label': msg['response_id'],
            'payload': api.db.json.dumps(refpol.parsed)
        }
Beispiel #19
0
    def do_upload_chunk(cls, params, response):
        # Make sure the directory exists
        try:
            os.makedirs(os.path.join(
                api.config.get('storage', 'bulk_storage_dir'),
                'tmp'))
        except:
            pass

        name = params['name'][:-4] if params['name'].endswith('.zip') else params['name']

        name = os.path.basename(name)  # be a little safer
        if not name:
          raise Exception("Invalid name for policy.")

        metadata = cls.Read({'id': name})

        if metadata is None:
            metadata = cls({
                'id': name,
                'written': params['index'],
                'total': params['total'],
                'tmpfile': os.path.join(
                    api.config.get('storage', 'bulk_storage_dir'),
                    "tmp",
                    params['name']
                )
            })

        elif 'tmpfile' not in metadata and 'disk_location' in metadata:
            raise Exception('Policy already exists')
        elif metadata['written'] < params['index']:
            os.remove(metadata['tmpfile'])
            metadata.Delete()
            raise Exception("Received out-of-order chunk. "
                            "Expected {0}. Got {1}"
                            .format(metadata['written'], params['index']))

        metadata['written'] = params['index']

        mode = 'r+b' if os.path.exists(metadata['tmpfile']) else 'wb'

        with open(metadata['tmpfile'], mode) as fout:
            fout.seek(params['index'])
            raw_data = base64.b64decode(params['data'])
            fout.write(raw_data)
            fout.flush()

        metadata['written'] += params['length']
        if metadata['written'] == metadata['total']:
            try:
                metadata.extract_zipped_policy()
                module_info = metadata.read_policy_modules()
                sesearch_result = metadata.parse_policy_binary()

                errors = []

                supported_docs = {
                    'dsl': False,
                    'raw': False
                }

                # Do we have source rules?
                if len(module_info['error']) > 0:
                    errors.append(module_info['error'])
                else:
                    supported_docs['dsl'] = True

                # Do we have the binary rules?
                if len(sesearch_result['error']) > 0:
                    errors.append(sesearch_result['error'])
                else:
                    supported_docs['raw'] = True

                if not supported_docs['dsl'] and not supported_docs['raw']:
                    raise api.DisplayError("Cannot find binary policy or reference policy source in the zip file")

                if supported_docs['dsl'] is True:
                    # Import the policy into Lobster
                    lobster_import = { 'refpolicy': metadata.id, 'modules': [] }

                    lobster_json = ws_domains.call(
                        'lobster',
                        'translate_selinux',
                        lobster_import
                    )

                    # TODO check the results['error'] array to see if problems

                    metadata['documents'] = {
                        'dsl': {
                            'text': lobster_json,
                            'mode': 'dsl',
                            'digest': hashlib.md5(lobster_json).hexdigest() #hashlib.md5(api.db.json.dumps(lobster_json['result'])).hexdigest()
                        }
                    }

                metadata['supported_docs'] = supported_docs

                metadata['modules'] = module_info['data']

                if 'documents' not in metadata:
                    metadata['documents'] = {}
                metadata['documents']['raw'] = {
                    'text': sesearch_result['data'],
                    'mode': 'raw',
                    'digest': hashlib.md5(sesearch_result['data']).hexdigest()
                }
            except Exception:
                metadata.Delete()
                raise
            else:
                metadata['valid'] = True

        metadata.Insert()

        response['payload'] = {
            'progress': float(metadata['written']) / float(metadata['total']),
            'info': {
                '_id': metadata['_id'],
                'id': metadata['id']
            }
        }

        return response