예제 #1
0
def main() -> None:
    baseflt = db.passive.searchrecontype("DNS_ANSWER")
    subdomains = False
    try:
        opts, args = getopt.getopt(
            sys.argv[1:],
            "s:h",
            [
                # filters
                "sensor=",
                # subdomains
                "sub",
                "help",
            ],
        )
    except getopt.GetoptError as err:
        sys.stderr.write(str(err) + "\n")
        sys.exit(-1)
    for o, a in opts:
        if o in ["-s", "--sensor"]:
            baseflt = db.passive.flt_and(
                baseflt, db.passive.searchsensor(utils.str2list(a)))
        elif o == "--sub":
            subdomains = True
        elif o in ["-h", "--help"]:
            sys.stdout.write("usage: %s [-h] [-s SENSOR] [--sub]"
                             "\n\n" % (sys.argv[0]))
            sys.stdout.write(__doc__)
            sys.stdout.write("\n\n")
            sys.exit(0)
        else:
            sys.stderr.write(
                "%r %r not understood (this is probably a bug).\n" % (o, a))
            sys.exit(-1)
    first = True
    flts = []
    for a in args:
        if first:
            first = False
        else:
            print()
        if utils.IPADDR.search(a) or a.isdigit():
            flts.append(db.passive.flt_and(baseflt, db.passive.searchhost(a)))
        else:
            flts += [
                db.passive.flt_and(
                    baseflt,
                    db.passive.searchdns(utils.str2regexp(a),
                                         subdomains=subdomains),
                ),
                db.passive.flt_and(
                    baseflt,
                    db.passive.searchdns(utils.str2regexp(a),
                                         reverse=True,
                                         subdomains=subdomains),
                ),
            ]
    for flt in flts:
        for r in db.passive.get(flt, sort=[("source", 1)]):
            disp_rec(r)
예제 #2
0
파일: webutils.py 프로젝트: fr830/ivre
def flt_from_query(query, base_flt=None):
    """Return a tuple (`flt`, `archive`, `sortby`, `unused`, `skip`,
    `limit`):

      - a filter based on the query

      - a boolean (`True` iff the filter should be applied to the
        archive collection)

      - a list of [`key`, `order`] to sort results

      - a list of the unused elements of the query (errors)

      - an integer for the number of results to skip

      - an integer for the maximum number of results to return

    """
    unused = []
    sortby = []
    archive = False
    skip = 0
    limit = None
    flt = get_init_flt() if base_flt is None else base_flt

    def add_unused(neg, param, value):
        """Add to the `unused` list a string representing (neg, param,
        value).

        """
        unused.append("%s%s" %
                      ('-' if neg else '', "%s=%s" %
                       (param, value) if value is not None else param))

    for (neg, param, value) in query:
        if not neg and param == 'skip':
            skip = int(value)
        elif not neg and param == 'limit':
            limit = int(value)
        elif param == "archives":
            archive = not neg
        elif param == "id":
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchobjectid(value.replace('-', ',').split(','),
                                       neg=neg))
        elif param == "host":
            flt = db.nmap.flt_and(flt, db.nmap.searchhost(value, neg=neg))
        elif param == "net":
            flt = db.nmap.flt_and(flt, db.nmap.searchnet(value, neg=neg))
        elif param == "range":
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchrange(*value.replace('-', ',').split(',', 1),
                                    neg=neg))
        elif param == "label":
            group, lab = ((None, None) if value is None else map(
                utils.str2regexp, value.split(':', 1)) if ':' in value else
                          (utils.str2regexp(value), None))
            flt = db.nmap.flt_and(
                flt, db.nmap.searchlabel(group=group, label=lab, neg=neg))
        elif param == "countports":
            vals = [int(val) for val in value.replace('-', ',').split(',', 1)]
            if len(vals) == 1:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchcountopenports(minn=vals[0],
                                                 maxn=vals[0],
                                                 neg=neg))
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchcountopenports(minn=vals[0],
                                                 maxn=vals[1],
                                                 neg=neg))
        elif param == "hostname":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchhostname(utils.str2regexp(value), neg=neg))
        elif param == "domain":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchdomain(utils.str2regexp(value), neg=neg))
        elif param == "category":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchcategory(utils.str2regexp(value), neg=neg))
        elif param == "country":
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchcountry(utils.str2list(value.upper()), neg=neg))
        elif param == "city":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchcity(utils.str2regexp(value), neg=neg))
        elif param == "asnum":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchasnum(utils.str2list(value), neg=neg))
        elif param == "asname":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchasname(utils.str2regexp(value), neg=neg))
        elif param == "source":
            flt = db.nmap.flt_and(flt, db.nmap.searchsource(value, neg=neg))
        elif param == "timerange":
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchtimerange(*map(
                    float,
                    value.replace('-', ',').split(',')),
                                        neg=neg))
        elif param == 'timeago':
            if value and value[-1].isalpha():
                unit = {
                    's': 1,
                    'm': 60,
                    'h': 3600,
                    'd': 86400,
                    'y': 31557600,
                }[value[-1]]
                timeago = int(value[:-1]) * unit
            else:
                timeago = int(value)
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchtimeago(datetime.timedelta(0, timeago), neg=neg))
        elif not neg and param == "service":
            if ':' in value:
                req, port = value.split(':', 1)
                port = int(port)
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchservice(utils.str2regexp(req),
                                               port=port))
            else:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchservice(utils.str2regexp(value)))
        elif not neg and param == "product" and ":" in value:
            product = value.split(':', 2)
            if len(product) == 2:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(utils.str2regexp(product[1]),
                                          service=utils.str2regexp(
                                              product[0])))
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(utils.str2regexp(product[1]),
                                          service=utils.str2regexp(product[0]),
                                          port=int(product[2])))
        elif not neg and param == "version" and value.count(":") >= 2:
            product = value.split(':', 3)
            if len(product) == 3:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                    ))
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(utils.str2regexp(product[1]),
                                          version=utils.str2regexp(product[2]),
                                          service=utils.str2regexp(product[0]),
                                          port=int(product[3])))
        elif not neg and param == "script":
            value = value.split(':', 1)
            if len(value) == 1:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchscript(name=utils.str2regexp(value[0])),
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchscript(
                        name=utils.str2regexp(value[0]),
                        output=utils.str2regexp(value[1]),
                    ),
                )
        # results of scripts or version scans
        elif not neg and param == "anonftp":
            flt = db.nmap.flt_and(flt, db.nmap.searchftpanon())
        elif not neg and param == 'anonldap':
            flt = db.nmap.flt_and(flt, db.nmap.searchldapanon())
        elif not neg and param == 'authbypassvnc':
            flt = db.nmap.flt_and(flt, db.nmap.searchvncauthbypass())
        elif not neg and param == "authhttp":
            flt = db.nmap.flt_and(flt, db.nmap.searchhttpauth())
        elif not neg and param == 'banner':
            flt = db.nmap.flt_and(
                flt, db.nmap.searchbanner(utils.str2regexp(value)))
        elif param == 'cookie':
            flt = db.nmap.flt_and(flt, db.nmap.searchcookie(value))
        elif param == 'file':
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchfile())
            else:
                value = value.split(':', 1)
                if len(value) == 1:
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchfile(fname=utils.str2regexp(value[0])))
                else:
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchfile(fname=utils.str2regexp(value[1]),
                                           scripts=value[0].split(',')))
        elif not neg and param == 'geovision':
            flt = db.nmap.flt_and(flt, db.nmap.searchgeovision())
        elif param == 'httptitle':
            flt = db.nmap.flt_and(
                flt, db.nmap.searchhttptitle(utils.str2regexp(value)))
        elif not neg and param == "nfs":
            flt = db.nmap.flt_and(flt, db.nmap.searchnfs())
        elif not neg and param in ["nis", "yp"]:
            flt = db.nmap.flt_and(flt, db.nmap.searchypserv())
        elif not neg and param == 'mssqlemptypwd':
            flt = db.nmap.flt_and(flt, db.nmap.searchmssqlemptypwd())
        elif not neg and param == 'mysqlemptypwd':
            flt = db.nmap.flt_and(flt, db.nmap.searchmysqlemptypwd())
        elif not neg and param == 'sshkey':
            if value:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchsshkey(output=utils.str2regexp(value)))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey())
        elif not neg and param.startswith('sshkey.'):
            subfield = param.split('.', 1)[1]
            if subfield in ['fingerprint', 'key', 'type', 'bits']:
                if subfield == 'type':
                    subfield = 'keytype'
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchsshkey(
                        **{subfield: utils.str2regexp(value)}))
            else:
                add_unused(neg, param, value)
        elif not neg and param == 'owa':
            flt = db.nmap.flt_and(flt, db.nmap.searchowa())
        elif param == 'phpmyadmin':
            flt = db.nmap.flt_and(flt, db.nmap.searchphpmyadmin())
        elif not neg and param.startswith('smb.'):
            flt = db.nmap.flt_and(
                flt, db.nmap.searchsmb(**{param[4:]: utils.str2regexp(value)}))
        elif not neg and param == 'smbshare':
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchsmbshares(access="" if value is None else value),
            )
        elif param == 'torcert':
            flt = db.nmap.flt_and(flt, db.nmap.searchtorcert())
        elif not neg and param == 'webfiles':
            flt = db.nmap.flt_and(flt, db.nmap.searchwebfiles())
        elif not neg and param == "webmin":
            flt = db.nmap.flt_and(flt, db.nmap.searchwebmin())
        elif not neg and param == 'x11srv':
            flt = db.nmap.flt_and(flt, db.nmap.searchx11())
        elif not neg and param == 'x11open':
            flt = db.nmap.flt_and(flt, db.nmap.searchx11access())
        elif not neg and param == 'xp445':
            flt = db.nmap.flt_and(flt, db.nmap.searchxp445())
        # OS fingerprint
        elif not neg and param == "os":
            flt = db.nmap.flt_and(flt,
                                  db.nmap.searchos(utils.str2regexp(value)))
        # device types
        elif param in ['devicetype', 'devtype']:
            flt = db.nmap.flt_and(
                flt, db.nmap.searchdevicetype(utils.str2regexp(value)))
        elif param in ['netdev', 'networkdevice']:
            flt = db.nmap.flt_and(flt, db.nmap.searchnetdev())
        elif param == 'phonedev':
            flt = db.nmap.flt_and(flt, db.nmap.searchphonedev())
        # traceroute
        elif param == 'hop':
            if ':' in value:
                hop, ttl = value.split(':', 1)
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchhop(hop, ttl=int(ttl), neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchhop(value, neg=neg))
        elif param == 'hopname':
            flt = db.nmap.flt_and(flt, db.nmap.searchhopname(value, neg=neg))
        elif param == 'hopdomain':
            flt = db.nmap.flt_and(flt, db.nmap.searchhopdomain(value, neg=neg))
        # sort
        elif param == 'sortby':
            if neg:
                sortby.append((value, -1))
            else:
                sortby.append((value, 1))
        elif param in ['open', 'filtered', 'closed']:
            if '_' in value:
                value = value.replace('_', '/')
            if '/' in value:
                proto, port = value.split('/')
            else:
                proto, port = "tcp", value
            port = port.split(',')
            if len(port) > 1:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchports([int(p) for p in port],
                                        protocol=proto,
                                        state=param))
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchport(int(port[0]),
                                       protocol=proto,
                                       state=param))
        elif param == 'otheropenport':
            flt = db.nmap.flt_and(
                flt, db.nmap.searchportsother(map(int, value.split(','))))
        elif param == "screenshot":
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(neg=neg))
            elif value.isdigit():
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchscreenshot(port=int(value), neg=neg))
            elif value.startswith('tcp/') or value.startswith('udp/'):
                value = value.split('/', 1)
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchscreenshot(port=int(value[1]),
                                             protocol=value[0],
                                             neg=neg))
            else:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchscreenshot(service=value, neg=neg))
        elif param == "screenwords":
            if value is None:
                flt = db.nmap.flt_and(flt,
                                      db.nmap.searchscreenshot(words=not neg))
            else:
                params = value.split(':', 1)
                words = (map(utils.str2regexp, params[0].split(','))
                         if ',' in params[0] else utils.str2regexp(params[0]))
                if len(params) == 1:
                    flt = db.nmap.flt_and(
                        flt, db.nmap.searchscreenshot(words=words, neg=neg))
                elif params[1].isdigit():
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchscreenshot(port=int(value),
                                                 neg=neg,
                                                 words=words))
                elif (params[1].startswith('tcp/')
                      or params[1].startswith('udp/')):
                    params[1] = params[1].split('/', 1)
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchscreenshot(port=int(params[1][1]),
                                                 protocol=params[1][0],
                                                 neg=neg,
                                                 words=words))
                else:
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchscreenshot(service=value,
                                                 neg=neg,
                                                 words=words))
        elif param == "cpe":
            if value:
                cpe_kwargs = {}
                cpe_fields = ["cpe_type", "vendor", "product", "version"]
                for field, cpe_arg in zip(cpe_fields, value.split(':', 3)):
                    cpe_kwargs[field] = utils.str2regexp(cpe_arg)
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe(**cpe_kwargs))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe())
        elif param == 'display':
            # ignore this parameter
            pass
        elif value is None:
            if param.startswith('tcp_') or param.startswith('tcp/') or \
               param.startswith('udp_') or param.startswith('udp/'):
                proto, port = param.replace('_', '/').split('/', 1)
                port = int(port)
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchport(port, protocol=proto, neg=neg))
            elif param == "openport":
                flt = db.nmap.flt_and(flt, db.nmap.searchopenport(neg=neg))
            elif param.isdigit():
                flt = db.nmap.flt_and(flt,
                                      db.nmap.searchport(int(param), neg=neg))
            elif all(x.isdigit() for x in param.split(',')):
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchports(map(int, param.split(',')), neg=neg))
            elif IPADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchhost(param, neg=neg))
            elif NETADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchnet(param, neg=neg))
            elif get_notepad_pages is not None and param == 'notes':
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchhosts(get_notepad_pages(), neg=neg))
            elif '<' in param:
                param = param.split('<', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchcmp(param[0], int(param[1][1:]),
                                          '>' if neg else '<='))
                else:
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchcmp(param[0], int(param[1]),
                                          '>=' if neg else '<'))
            elif '>' in param:
                param = param.split('>', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchcmp(param[0], int(param[1][1:]),
                                          '<' if neg else '>='))
                else:
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchcmp(param[0], int(param[1]),
                                          '<=' if neg else '>'))
            else:
                add_unused(neg, param, value)
        else:
            add_unused(neg, param, value)
    return flt, archive, sortby, unused, skip, limit
예제 #3
0
def flt_from_query(query, base_flt=None):
    """Return a tuple (`flt`, `sortby`, `unused`, `skip`, `limit`):

      - a filter based on the query

      - a list of [`key`, `order`] to sort results

      - a list of the unused elements of the query (errors)

      - an integer for the number of results to skip

      - an integer for the maximum number of results to return

    """
    unused = []
    sortby = []
    skip = 0
    limit = None
    flt = get_init_flt() if base_flt is None else base_flt

    def add_unused(neg, param, value):
        """Add to the `unused` list a string representing (neg, param,
        value).

        """
        unused.append("%s%s" %
                      ('-' if neg else '', "%s=%s" %
                       (param, value) if value is not None else param))

    for (neg, param, value) in query:
        if not neg and param == 'skip':
            skip = int(value)
        elif not neg and param == 'limit':
            limit = int(value)
        elif param == "id":
            flt = db.view.flt_and(
                flt,
                db.view.searchobjectid(value.replace('-', ',').split(','),
                                       neg=neg))
        elif param == "host":
            flt = db.view.flt_and(flt, db.view.searchhost(value, neg=neg))
        elif param == "net":
            flt = db.view.flt_and(flt, db.view.searchnet(value, neg=neg))
        elif param == "range":
            flt = db.view.flt_and(
                flt,
                db.view.searchrange(*value.replace('-', ',').split(',', 1),
                                    neg=neg))
        elif param == "countports":
            vals = [int(val) for val in value.replace('-', ',').split(',', 1)]
            if len(vals) == 1:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchcountopenports(minn=vals[0],
                                                 maxn=vals[0],
                                                 neg=neg))
            else:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchcountopenports(minn=vals[0],
                                                 maxn=vals[1],
                                                 neg=neg))
        elif param == "hostname":
            flt = db.view.flt_and(
                flt, db.view.searchhostname(utils.str2regexp(value), neg=neg))
        elif param == "domain":
            flt = db.view.flt_and(
                flt, db.view.searchdomain(utils.str2regexp(value), neg=neg))
        elif param == "category":
            flt = db.view.flt_and(
                flt, db.view.searchcategory(utils.str2regexp(value), neg=neg))
        elif param == "country":
            flt = db.view.flt_and(
                flt,
                db.view.searchcountry(utils.str2list(value.upper()), neg=neg))
        elif param == "city":
            flt = db.view.flt_and(
                flt, db.view.searchcity(utils.str2regexp(value), neg=neg))
        elif param == "asnum":
            flt = db.view.flt_and(
                flt, db.view.searchasnum(utils.str2list(value), neg=neg))
        elif param == "asname":
            flt = db.view.flt_and(
                flt, db.view.searchasname(utils.str2regexp(value), neg=neg))
        elif param == "source":
            flt = db.view.flt_and(flt, db.view.searchsource(value, neg=neg))
        elif param == "timerange":
            flt = db.view.flt_and(
                flt,
                db.view.searchtimerange(
                    *(float(val)
                      for val in value.replace('-', ',').split(',')),
                    neg=neg))
        elif param == 'timeago':
            if value and value[-1].isalpha():
                unit = {
                    's': 1,
                    'm': 60,
                    'h': 3600,
                    'd': 86400,
                    'y': 31557600,
                }[value[-1]]
                timeago = int(value[:-1]) * unit
            else:
                timeago = int(value)
            flt = db.view.flt_and(
                flt,
                db.view.searchtimeago(datetime.timedelta(0, timeago), neg=neg))
        elif not neg and param == "service":
            if ':' in value:
                req, port = value.split(':', 1)
                port = int(port)
                flt = db.view.flt_and(
                    flt, db.view.searchservice(utils.str2regexp(req),
                                               port=port))
            else:
                flt = db.view.flt_and(
                    flt, db.view.searchservice(utils.str2regexp(value)))
        elif not neg and param == "product" and ":" in value:
            product = value.split(':', 2)
            if len(product) == 2:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchproduct(utils.str2regexp(product[1]),
                                          service=utils.str2regexp(
                                              product[0])))
            else:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchproduct(utils.str2regexp(product[1]),
                                          service=utils.str2regexp(product[0]),
                                          port=int(product[2])))
        elif not neg and param == "version" and value.count(":") >= 2:
            product = value.split(':', 3)
            if len(product) == 3:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                    ))
            else:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchproduct(utils.str2regexp(product[1]),
                                          version=utils.str2regexp(product[2]),
                                          service=utils.str2regexp(product[0]),
                                          port=int(product[3])))
        elif param == "script":
            value = value.split(':', 1)
            if len(value) == 1:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchscript(name=utils.str2regexp(value[0]),
                                         neg=neg),
                )
            else:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchscript(name=utils.str2regexp(value[0]),
                                         output=utils.str2regexp(value[1]),
                                         neg=neg),
                )
        # results of scripts or version scans
        elif not neg and param == "anonftp":
            flt = db.view.flt_and(flt, db.view.searchftpanon())
        elif not neg and param == 'anonldap':
            flt = db.view.flt_and(flt, db.view.searchldapanon())
        elif not neg and param == 'authbypassvnc':
            flt = db.view.flt_and(flt, db.view.searchvncauthbypass())
        elif not neg and param == "authhttp":
            flt = db.view.flt_and(flt, db.view.searchhttpauth())
        elif not neg and param == 'banner':
            flt = db.view.flt_and(
                flt, db.view.searchbanner(utils.str2regexp(value)))
        elif param == 'cookie':
            flt = db.view.flt_and(flt, db.view.searchcookie(value))
        elif param == 'file':
            if value is None:
                flt = db.view.flt_and(flt, db.view.searchfile())
            else:
                value = value.split(':', 1)
                if len(value) == 1:
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchfile(fname=utils.str2regexp(value[0])))
                else:
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchfile(fname=utils.str2regexp(value[1]),
                                           scripts=value[0].split(',')))
        elif param == 'vuln':
            try:
                vulnid, status = value.split(':', 1)
            except ValueError:
                vulnid = value
                status = None
            except AttributeError:
                vulnid = None
                status = None
            flt = db.view.flt_and(
                flt, db.view.searchvuln(vulnid=vulnid, status=status))
        elif not neg and param == 'geovision':
            flt = db.view.flt_and(flt, db.view.searchgeovision())
        elif param == 'httptitle':
            flt = db.view.flt_and(
                flt, db.view.searchhttptitle(utils.str2regexp(value)))
        elif not neg and param == "nfs":
            flt = db.view.flt_and(flt, db.view.searchnfs())
        elif not neg and param in ["nis", "yp"]:
            flt = db.view.flt_and(flt, db.view.searchypserv())
        elif not neg and param == 'mssqlemptypwd':
            flt = db.view.flt_and(flt, db.view.searchmssqlemptypwd())
        elif not neg and param == 'mysqlemptypwd':
            flt = db.view.flt_and(flt, db.view.searchmysqlemptypwd())
        elif not neg and param == 'sshkey':
            if value:
                flt = db.view.flt_and(
                    flt, db.view.searchsshkey(output=utils.str2regexp(value)))
            else:
                flt = db.view.flt_and(flt, db.view.searchsshkey())
        elif not neg and param.startswith('sshkey.'):
            subfield = param.split('.', 1)[1]
            if subfield in ['fingerprint', 'key', 'type', 'bits']:
                if subfield == 'type':
                    subfield = 'keytype'
                elif subfield == 'bits':
                    try:
                        value = int(value)
                    except (ValueError, TypeError):
                        pass
                else:
                    value = utils.str2regexp(value)
                flt = db.view.flt_and(
                    flt, db.view.searchsshkey(**{subfield: value}))
            else:
                add_unused(neg, param, value)
        elif not neg and param == 'httphdr':
            if value is None:
                flt = db.view.flt_and(flt, db.view.searchhttphdr())
            elif ':' in value:
                name, value = (utils.str2regexp(string)
                               for string in value.split(':', 1))
                flt = db.view.flt_and(
                    flt, db.view.searchhttphdr(name=name, value=value))
            else:
                flt = db.view.flt_and(
                    flt, db.view.searchhttphdr(name=utils.str2regexp(value)))
        elif not neg and param == 'owa':
            flt = db.view.flt_and(flt, db.view.searchowa())
        elif param == 'phpmyadmin':
            flt = db.view.flt_and(flt, db.view.searchphpmyadmin())
        elif not neg and param.startswith('smb.'):
            flt = db.view.flt_and(
                flt, db.view.searchsmb(**{param[4:]: utils.str2regexp(value)}))
        elif not neg and param == 'smbshare':
            flt = db.view.flt_and(
                flt,
                db.view.searchsmbshares(access="" if value is None else value),
            )
        elif param == 'torcert':
            flt = db.view.flt_and(flt, db.view.searchtorcert())
        elif not neg and param == 'webfiles':
            flt = db.view.flt_and(flt, db.view.searchwebfiles())
        elif not neg and param == "webmin":
            flt = db.view.flt_and(flt, db.view.searchwebmin())
        elif not neg and param == 'x11srv':
            flt = db.view.flt_and(flt, db.view.searchx11())
        elif not neg and param == 'x11open':
            flt = db.view.flt_and(flt, db.view.searchx11access())
        elif not neg and param == 'xp445':
            flt = db.view.flt_and(flt, db.view.searchxp445())
        elif param == "ssl-ja3-client":
            flt = db.view.flt_and(
                flt,
                db.view.searchja3client(
                    value_or_hash=(None if value is None else
                                   utils.str2regexp(value)),
                    neg=neg))
        elif param == "ssl-ja3-server":
            if value is None:
                # There are no additional arguments
                flt = db.view.flt_and(flt, db.view.searchja3server(neg=neg))
            else:
                split = [
                    utils.str2regexp(v) if v else None
                    for v in value.split(':', 1)
                ]
                if len(split) == 1:
                    # Only a JA3 server is given
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchja3server(
                            value_or_hash=(split[0]),
                            neg=neg,
                        ))
                else:
                    # Both client and server JA3 are specified
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchja3server(
                            value_or_hash=split[0],
                            client_value_or_hash=split[1],
                            neg=neg,
                        ))
        elif param == "useragent":
            if value:
                flt = db.view.flt_and(
                    flt,
                    db.view.searchuseragent(useragent=utils.str2regexp(value)))
            else:
                flt = db.view.flt_and(flt, db.view.searchuseragent())
        # OS fingerprint
        elif not neg and param == "os":
            flt = db.view.flt_and(flt,
                                  db.view.searchos(utils.str2regexp(value)))
        # device types
        elif param in ['devicetype', 'devtype']:
            flt = db.view.flt_and(
                flt, db.view.searchdevicetype(utils.str2regexp(value)))
        elif param in ['netdev', 'networkdevice']:
            flt = db.view.flt_and(flt, db.view.searchnetdev())
        elif param == 'phonedev':
            flt = db.view.flt_and(flt, db.view.searchphonedev())
        # traceroute
        elif param == 'hop':
            if ':' in value:
                hop, ttl = value.split(':', 1)
                flt = db.view.flt_and(
                    flt, db.view.searchhop(hop, ttl=int(ttl), neg=neg))
            else:
                flt = db.view.flt_and(flt, db.view.searchhop(value, neg=neg))
        elif param == 'hopname':
            flt = db.view.flt_and(flt, db.view.searchhopname(value, neg=neg))
        elif param == 'hopdomain':
            flt = db.view.flt_and(flt, db.view.searchhopdomain(value, neg=neg))
        elif not neg and param in [
                "ike.vendor_id.name", "ike.vendor_id.value"
        ]:
            flt = db.view.flt_and(
                flt,
                db.view.searchscript(
                    name="ike-info",
                    values={
                        'vendor_ids.%s' % param[14:]: utils.str2regexp(value)
                    },
                ),
            )
        elif not neg and param == "ike.notification":
            flt = db.view.flt_and(
                flt,
                db.view.searchscript(
                    name="ike-info",
                    values={'notification_type': utils.str2regexp(value)},
                ),
            )
        # sort
        elif param == 'sortby':
            if neg:
                sortby.append((value, -1))
            else:
                sortby.append((value, 1))
        elif param in ['open', 'filtered', 'closed']:
            value = value.replace('_', '/').split(',')
            protos = {}
            for port in value:
                if '/' in port:
                    proto, port = port.split('/')
                else:
                    proto, port = "tcp", port
                protos.setdefault(proto, []).append(int(port))
            for proto, ports in viewitems(protos):
                flt = db.view.flt_and(
                    flt,
                    db.view.searchport(ports[0], protocol=proto, state=param)
                    if len(ports) == 1 else db.view.searchports(
                        ports, protocol=proto, state=param))
        elif param == 'otheropenport':
            flt = db.view.flt_and(
                flt,
                db.view.searchportsother(
                    [int(val) for val in value.split(',')]))
        elif param == "screenshot":
            if value is None:
                flt = db.view.flt_and(flt, db.view.searchscreenshot(neg=neg))
            elif value.isdigit():
                flt = db.view.flt_and(
                    flt, db.view.searchscreenshot(port=int(value), neg=neg))
            elif value.startswith('tcp/') or value.startswith('udp/'):
                value = value.split('/', 1)
                flt = db.view.flt_and(
                    flt,
                    db.view.searchscreenshot(port=int(value[1]),
                                             protocol=value[0],
                                             neg=neg))
            else:
                flt = db.view.flt_and(
                    flt, db.view.searchscreenshot(service=value, neg=neg))
        elif param == "screenwords":
            if value is None:
                flt = db.view.flt_and(flt,
                                      db.view.searchscreenshot(words=not neg))
            else:
                params = value.split(':', 1)
                words = ([
                    utils.str2regexp(elt) for elt in params[0].split(',')
                ] if ',' in params[0] else utils.str2regexp(params[0]))
                if len(params) == 1:
                    flt = db.view.flt_and(
                        flt, db.view.searchscreenshot(words=words, neg=neg))
                elif params[1].isdigit():
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchscreenshot(port=int(value),
                                                 neg=neg,
                                                 words=words))
                elif (params[1].startswith('tcp/')
                      or params[1].startswith('udp/')):
                    params[1] = params[1].split('/', 1)
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchscreenshot(port=int(params[1][1]),
                                                 protocol=params[1][0],
                                                 neg=neg,
                                                 words=words))
                else:
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchscreenshot(service=value,
                                                 neg=neg,
                                                 words=words))
        elif param == "cpe":
            if value:
                cpe_kwargs = {}
                cpe_fields = ["cpe_type", "vendor", "product", "version"]
                for field, cpe_arg in zip(cpe_fields, value.split(':', 3)):
                    cpe_kwargs[field] = utils.str2regexp(cpe_arg)
                flt = db.view.flt_and(flt, db.view.searchcpe(**cpe_kwargs))
            else:
                flt = db.view.flt_and(flt, db.view.searchcpe())
        elif param == 'display':
            # ignore this parameter
            pass
        elif value is None:
            if param.startswith('tcp_') or param.startswith('tcp/') or \
               param.startswith('udp_') or param.startswith('udp/'):
                proto, port = param.replace('_', '/').split('/', 1)
                port = int(port)
                flt = db.view.flt_and(
                    flt, db.view.searchport(port, protocol=proto, neg=neg))
            elif param == "openport":
                flt = db.view.flt_and(flt, db.view.searchopenport(neg=neg))
            elif param.isdigit():
                flt = db.view.flt_and(flt,
                                      db.view.searchport(int(param), neg=neg))
            elif all(x.isdigit() for x in param.split(',')):
                flt = db.view.flt_and(
                    flt,
                    db.view.searchports([int(val) for val in param.split(',')],
                                        neg=neg))
            elif IPADDR.match(param):
                flt = db.view.flt_and(flt, db.view.searchhost(param, neg=neg))
            elif NETADDR.match(param):
                flt = db.view.flt_and(flt, db.view.searchnet(param, neg=neg))
            elif get_notepad_pages is not None and param == 'notes':
                flt = db.view.flt_and(
                    flt, db.view.searchhosts(get_notepad_pages(), neg=neg))
            elif '<' in param:
                param = param.split('<', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchcmp(param[0], int(param[1][1:]),
                                          '>' if neg else '<='))
                else:
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchcmp(param[0], int(param[1]),
                                          '>=' if neg else '<'))
            elif '>' in param:
                param = param.split('>', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchcmp(param[0], int(param[1][1:]),
                                          '<' if neg else '>='))
                else:
                    flt = db.view.flt_and(
                        flt,
                        db.view.searchcmp(param[0], int(param[1]),
                                          '<=' if neg else '>'))
            else:
                add_unused(neg, param, value)
        else:
            add_unused(neg, param, value)
    return flt, sortby, unused, skip, limit
예제 #4
0
파일: webutils.py 프로젝트: Gowabby/ivre
def flt_from_query(query, base_flt=None):
    """Return a tuple (`flt`, `archive`, `sortby`, `unused`, `skip`,
    `limit`):

      - a filter based on the query

      - a boolean (`True` iff the filter should be applied to the
        archive collection)

      - a list of [`key`, `order`] to sort results

      - a list of the unused elements of the query (errors)

      - an integer for the number of results to skip

      - an integer for the maximum number of results to return

    """
    unused = []
    sortby = []
    archive = False
    skip = 0
    limit = None
    flt = get_init_flt() if base_flt is None else base_flt
    def add_unused(neg, param, value):
        """Add to the `unused` list a string representing (neg, param,
        value).

        """
        unused.append("%s%s" % (
            '-' if neg else '',
            "%s=%s" % (param, value) if value is not None else param
        ))
    for (neg, param, value) in query:
        if not neg and param == 'skip':
            skip = int(value)
        elif not neg and param == 'limit':
            limit = int(value)
        elif param == "archives":
            archive = not neg
        elif param == "id":
            flt = db.nmap.flt_and(flt, db.nmap.searchobjectid(
                value.replace('-', ',').split(','),
                neg=neg))
        elif param == "host":
            flt = db.nmap.flt_and(flt, db.nmap.searchhost(value, neg=neg))
        elif param == "net":
            flt = db.nmap.flt_and(flt, db.nmap.searchnet(value, neg=neg))
        elif param == "range":
            flt = db.nmap.flt_and(flt, db.nmap.searchrange(
                *value.replace('-', ',').split(',', 1),
                neg=neg))
        elif param == "label":
            group, lab = ((None, None)
                          if value is None else
                          map(utils.str2regexp, value.split(':', 1))
                          if ':' in value else
                          (utils.str2regexp(value), None))
            flt = db.nmap.flt_and(flt, db.nmap.searchlabel(group=group,
                                                           label=lab, neg=neg))
        elif param == "countports":
            vals = [int(val) for val in value.replace('-', ',').split(',', 1)]
            if len(vals) == 1:
                flt = db.nmap.flt_and(flt, db.nmap.searchcountopenports(
                    minn=vals[0], maxn=vals[0], neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchcountopenports(
                    minn=vals[0], maxn=vals[1], neg=neg))
        elif param == "hostname":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchhostname(utils.str2regexp(value), neg=neg))
        elif param == "domain":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchdomain(utils.str2regexp(value), neg=neg))
        elif param == "category":
            flt = db.nmap.flt_and(flt, db.nmap.searchcategory(
                utils.str2regexp(value), neg=neg))
        elif param == "country":
            flt = db.nmap.flt_and(flt, db.nmap.searchcountry(
                utils.str2list(value.upper()), neg=neg))
        elif param == "city":
            flt = db.nmap.flt_and(flt, db.nmap.searchcity(
                utils.str2regexp(value), neg=neg))
        elif param == "asnum":
            flt = db.nmap.flt_and(flt, db.nmap.searchasnum(
                utils.str2list(value), neg=neg))
        elif param == "asname":
            flt = db.nmap.flt_and(flt, db.nmap.searchasname(
                utils.str2regexp(value), neg=neg))
        elif param == "source":
            flt = db.nmap.flt_and(flt, db.nmap.searchsource(value, neg=neg))
        elif param == "timerange":
            flt = db.nmap.flt_and(flt, db.nmap.searchtimerange(
                *map(float, value.replace('-', ',').split(',')),
                neg=neg))
        elif param == 'timeago':
            if value and value[-1].isalpha():
                unit = {
                    's': 1,
                    'm': 60,
                    'h': 3600,
                    'd': 86400,
                    'y': 31557600,
                }[value[-1]]
                timeago = int(value[:-1]) * unit
            else:
                timeago = int(value)
            flt = db.nmap.flt_and(flt, db.nmap.searchtimeago(
                datetime.timedelta(0, timeago), neg=neg))
        elif not neg and param == "service":
            if ':' in value:
                req, port = value.split(':', 1)
                port = int(port)
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchservice(utils.str2regexp(req), port=port))
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchservice(utils.str2regexp(value)))
        elif not neg and param == "product" and ":" in value:
            product = value.split(':', 2)
            if len(product) == 2:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        service=utils.str2regexp(product[0])
                    )
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        service=utils.str2regexp(product[0]),
                        port=int(product[2])
                    )
                )
        elif not neg and param == "version" and value.count(":") >= 2:
            product = value.split(':', 3)
            if len(product) == 3:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                    )
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                        port=int(product[3])
                    )
                )
        elif not neg and param == "script":
            value = value.split(':', 1)
            if len(value) == 1:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchscript(name=utils.str2regexp(value[0])),
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchscript(
                        name=utils.str2regexp(value[0]),
                        output=utils.str2regexp(value[1]),
                    ),
                )
        # results of scripts or version scans
        elif not neg and param == "anonftp":
            flt = db.nmap.flt_and(flt, db.nmap.searchftpanon())
        elif not neg and param == 'anonldap':
            flt = db.nmap.flt_and(flt, db.nmap.searchldapanon())
        elif not neg and param == 'authbypassvnc':
            flt = db.nmap.flt_and(flt, db.nmap.searchvncauthbypass())
        elif not neg and param == "authhttp":
            flt = db.nmap.flt_and(flt, db.nmap.searchhttpauth())
        elif not neg and param == 'banner':
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchbanner(utils.str2regexp(value)))
        elif param == 'cookie':
            flt = db.nmap.flt_and(flt, db.nmap.searchcookie(value))
        elif param == 'file':
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchfile())
            else:
                value = value.split(':', 1)
                if len(value) == 1:
                    flt = db.nmap.flt_and(flt, db.nmap.searchfile(
                        fname=utils.str2regexp(value[0])))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchfile(
                        fname=utils.str2regexp(value[1]),
                        scripts=value[0].split(',')))
        elif not neg and param == 'geovision':
            flt = db.nmap.flt_and(flt, db.nmap.searchgeovision())
        elif param == 'httptitle':
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchhttptitle(utils.str2regexp(value)))
        elif not neg and param == "nfs":
            flt = db.nmap.flt_and(flt, db.nmap.searchnfs())
        elif not neg and param in ["nis", "yp"]:
            flt = db.nmap.flt_and(flt, db.nmap.searchypserv())
        elif not neg and param == 'mssqlemptypwd':
            flt = db.nmap.flt_and(flt, db.nmap.searchmssqlemptypwd())
        elif not neg and param == 'mysqlemptypwd':
            flt = db.nmap.flt_and(flt, db.nmap.searchmysqlemptypwd())
        elif not neg and param == 'sshkey':
            if value:
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey(
                    output=utils.str2regexp(value)))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey())
        elif not neg and param.startswith('sshkey.'):
            subfield = param.split('.', 1)[1]
            if subfield in ['fingerprint', 'key', 'type', 'bits']:
                if subfield == 'type':
                    subfield = 'keytype'
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey(
                    **{subfield: utils.str2regexp(value)}))
            else:
                add_unused(neg, param, value)
        elif not neg and param == 'owa':
            flt = db.nmap.flt_and(flt, db.nmap.searchowa())
        elif param == 'phpmyadmin':
            flt = db.nmap.flt_and(flt, db.nmap.searchphpmyadmin())
        elif not neg and param.startswith('smb.'):
            flt = db.nmap.flt_and(flt, db.nmap.searchsmb(
                **{param[4:]: utils.str2regexp(value)}))
        elif not neg and param == 'smbshare':
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchsmbshares(access="" if value is None else value),
            )
        elif param == 'torcert':
            flt = db.nmap.flt_and(flt, db.nmap.searchtorcert())
        elif not neg and param == 'webfiles':
            flt = db.nmap.flt_and(flt, db.nmap.searchwebfiles())
        elif not neg and param == "webmin":
            flt = db.nmap.flt_and(flt, db.nmap.searchwebmin())
        elif not neg and param == 'x11srv':
            flt = db.nmap.flt_and(flt, db.nmap.searchx11())
        elif not neg and param == 'x11open':
            flt = db.nmap.flt_and(flt, db.nmap.searchx11access())
        elif not neg and param == 'xp445':
            flt = db.nmap.flt_and(flt, db.nmap.searchxp445())
        # OS fingerprint
        elif not neg and param == "os":
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchos(utils.str2regexp(value)))
        # device types
        elif param in ['devicetype', 'devtype']:
            flt = db.nmap.flt_and(
                flt,
                db.nmap.searchdevicetype(utils.str2regexp(value)))
        elif param in ['netdev', 'networkdevice']:
            flt = db.nmap.flt_and(flt, db.nmap.searchnetdev())
        elif param == 'phonedev':
            flt = db.nmap.flt_and(flt, db.nmap.searchphonedev())
        # traceroute
        elif param == 'hop':
            if ':' in value:
                hop, ttl = value.split(':', 1)
                flt = db.nmap.flt_and(flt,
                                      db.nmap.searchhop(hop, ttl=int(ttl),
                                                        neg=neg))
            else:
                flt = db.nmap.flt_and(flt,
                                      db.nmap.searchhop(value, neg=neg))
        elif param == 'hopname':
            flt = db.nmap.flt_and(flt,
                                  db.nmap.searchhopname(value, neg=neg))
        elif param == 'hopdomain':
            flt = db.nmap.flt_and(flt,
                                  db.nmap.searchhopdomain(value, neg=neg))
        # sort
        elif param == 'sortby':
            if neg:
                sortby.append((value, -1))
            else:
                sortby.append((value, 1))
        elif param in ['open', 'filtered', 'closed']:
            value = value.replace('_', '/').split(',')
            protos = {}
            for port in value:
                if '/' in port:
                    proto, port = port.split('/')
                else:
                    proto, port = "tcp", port
                protos.setdefault(proto, []).append(int(port))
            for proto, ports in protos.iteritems():
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchport(ports[0], protocol=proto, state=param)
                    if len(ports) == 1 else
                    db.nmap.searchports(ports, protocol=proto, state=param)
                )
        elif param == 'otheropenport':
            flt = db.nmap.flt_and(
                flt, db.nmap.searchportsother(map(int, value.split(','))))
        elif param == "screenshot":
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(neg=neg))
            elif value.isdigit():
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                    port=int(value), neg=neg))
            elif value.startswith('tcp/') or value.startswith('udp/'):
                value = value.split('/', 1)
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                    port=int(value[1]), protocol=value[0], neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                    service=value, neg=neg))
        elif param == "screenwords":
            if value is None:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchscreenshot(words=not neg)
                )
            else:
                params = value.split(':', 1)
                words = (map(utils.str2regexp, params[0].split(','))
                         if ',' in params[0] else utils.str2regexp(params[0]))
                if len(params) == 1:
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                        words=words, neg=neg))
                elif params[1].isdigit():
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                        port=int(value), neg=neg, words=words))
                elif (params[1].startswith('tcp/')
                      or params[1].startswith('udp/')):
                    params[1] = params[1].split('/', 1)
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                        port=int(params[1][1]), protocol=params[1][0],
                        neg=neg, words=words))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(
                        service=value, neg=neg, words=words))
        elif param == "cpe":
            if value:
                cpe_kwargs = {}
                cpe_fields = ["cpe_type", "vendor", "product", "version"]
                for field, cpe_arg in zip(cpe_fields, value.split(':', 3)):
                    cpe_kwargs[field] = utils.str2regexp(cpe_arg)
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe(**cpe_kwargs))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe())
        elif param == 'display':
            # ignore this parameter
            pass
        elif value is None:
            if param.startswith('tcp_') or param.startswith('tcp/') or \
               param.startswith('udp_') or param.startswith('udp/'):
                proto, port = param.replace('_', '/').split('/', 1)
                port = int(port)
                flt = db.nmap.flt_and(flt, db.nmap.searchport(port,
                                                              protocol=proto,
                                                              neg=neg))
            elif param == "openport":
                flt = db.nmap.flt_and(flt, db.nmap.searchopenport(neg=neg))
            elif param.isdigit():
                flt = db.nmap.flt_and(flt, db.nmap.searchport(int(param),
                                                              neg=neg))
            elif all(x.isdigit() for x in param.split(',')):
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchports(map(int, param.split(',')), neg=neg)
                )
            elif IPADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchhost(param, neg=neg))
            elif NETADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchnet(param, neg=neg))
            elif get_notepad_pages is not None and param == 'notes':
                flt = db.nmap.flt_and(flt, db.nmap.searchhosts(
                    get_notepad_pages(), neg=neg))
            elif '<' in param:
                param = param.split('<', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(
                        param[0],
                        int(param[1][1:]),
                        '>' if neg else '<='))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(
                        param[0],
                        int(param[1]),
                        '>=' if neg else '<'))
            elif '>' in param:
                param = param.split('>', 1)
                if param[1] and param[1][0] == '=':
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(
                        param[0],
                        int(param[1][1:]),
                        '<' if neg else '>='))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(
                        param[0],
                        int(param[1]),
                        '<=' if neg else '>'))
            else:
                add_unused(neg, param, value)
        else:
            add_unused(neg, param, value)
    return flt, archive, sortby, unused, skip, limit
예제 #5
0
파일: webutils.py 프로젝트: roceys/ivre
def flt_from_query(query, base_flt=None):
    """Return a tuple (`flt`, `archive`, `sortby`, `unused`, `skip`,
    `limit`):

      - a filter based on the query

      - a boolean (`True` iff the filter should be applied to the
        archive collection)

      - a list of [`key`, `order`] to sort results

      - a list of the unused elements of the query (errors)

      - an integer for the number of results to skip

      - an integer for the maximum number of results to return

    """
    unused = []
    sortby = []
    archive = False
    skip = 0
    limit = None
    flt = get_init_flt() if base_flt is None else base_flt

    def add_unused(neg, param, value):
        """Add to the `unused` list a string representing (neg, param,
        value).

        """
        unused.append("%s%s" % ("-" if neg else "", "%s=%s" % (param, value) if value is not None else param))

    for (neg, param, value) in query:
        if not neg and param == "skip":
            skip = int(value)
        elif not neg and param == "limit":
            limit = int(value)
        elif param == "archives":
            archive = not neg
        elif param == "id":
            flt = db.nmap.flt_and(flt, db.nmap.searchobjectid(value.replace("-", ",").split(","), neg=neg))
        elif param == "host":
            flt = db.nmap.flt_and(flt, db.nmap.searchhost(value, neg=neg))
        elif param == "net":
            flt = db.nmap.flt_and(flt, db.nmap.searchnet(value, neg=neg))
        elif param == "range":
            flt = db.nmap.flt_and(flt, db.nmap.searchrange(*value.replace("-", ",").split(",", 1), neg=neg))
        elif param == "label":
            group, lab = (
                (None, None)
                if value is None
                else map(utils.str2regexp, value.split(":", 1))
                if ":" in value
                else (utils.str2regexp(value), None)
            )
            flt = db.nmap.flt_and(flt, db.nmap.searchlabel(group=group, label=lab, neg=neg))
        elif param == "countports":
            vals = [int(val) for val in value.replace("-", ",").split(",", 1)]
            if len(vals) == 1:
                flt = db.nmap.flt_and(flt, db.nmap.searchcountopenports(minn=vals[0], maxn=vals[0], neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchcountopenports(minn=vals[0], maxn=vals[1], neg=neg))
        elif param == "hostname":
            flt = db.nmap.flt_and(flt, db.nmap.searchhostname(utils.str2regexp(value), neg=neg))
        elif param == "domain":
            flt = db.nmap.flt_and(flt, db.nmap.searchdomain(utils.str2regexp(value), neg=neg))
        elif param == "category":
            flt = db.nmap.flt_and(flt, db.nmap.searchcategory(utils.str2regexp(value), neg=neg))
        elif param == "country":
            flt = db.nmap.flt_and(flt, db.nmap.searchcountry(utils.str2list(value.upper()), neg=neg))
        elif param == "city":
            flt = db.nmap.flt_and(flt, db.nmap.searchcity(utils.str2regexp(value), neg=neg))
        elif param == "asnum":
            flt = db.nmap.flt_and(flt, db.nmap.searchasnum(utils.str2list(value), neg=neg))
        elif param == "asname":
            flt = db.nmap.flt_and(flt, db.nmap.searchasname(utils.str2regexp(value), neg=neg))
        elif param == "source":
            flt = db.nmap.flt_and(flt, db.nmap.searchsource(value, neg=neg))
        elif param == "timerange":
            flt = db.nmap.flt_and(
                flt, db.nmap.searchtimerange(*map(float, value.replace("-", ",").split(",")), neg=neg)
            )
        elif param == "timeago":
            if value and value[-1].isalpha():
                unit = {"s": 1, "m": 60, "h": 3600, "d": 86400, "y": 31557600}[value[-1]]
                timeago = int(value[:-1]) * unit
            else:
                timeago = int(value)
            flt = db.nmap.flt_and(flt, db.nmap.searchtimeago(datetime.timedelta(0, timeago), neg=neg))
        elif not neg and param == "service":
            if ":" in value:
                req, port = value.split(":", 1)
                port = int(port)
                flt = db.nmap.flt_and(flt, db.nmap.searchservice(utils.str2regexp(req), port=port))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchservice(utils.str2regexp(value)))
        elif not neg and param == "product" and ":" in value:
            product = value.split(":", 2)
            if len(product) == 2:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchproduct(utils.str2regexp(product[1]), service=utils.str2regexp(product[0]))
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]), service=utils.str2regexp(product[0]), port=int(product[2])
                    ),
                )
        elif not neg and param == "version" and value.count(":") >= 2:
            product = value.split(":", 3)
            if len(product) == 3:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                    ),
                )
            else:
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchproduct(
                        utils.str2regexp(product[1]),
                        version=utils.str2regexp(product[2]),
                        service=utils.str2regexp(product[0]),
                        port=int(product[3]),
                    ),
                )
        elif not neg and param == "script":
            value = value.split(":", 1)
            if len(value) == 1:
                flt = db.nmap.flt_and(flt, db.nmap.searchscript(name=utils.str2regexp(value[0])))
            else:
                flt = db.nmap.flt_and(
                    flt, db.nmap.searchscript(name=utils.str2regexp(value[0]), output=utils.str2regexp(value[1]))
                )
        # results of scripts or version scans
        elif not neg and param == "anonftp":
            flt = db.nmap.flt_and(flt, db.nmap.searchftpanon())
        elif not neg and param == "anonldap":
            flt = db.nmap.flt_and(flt, db.nmap.searchldapanon())
        elif not neg and param == "authbypassvnc":
            flt = db.nmap.flt_and(flt, db.nmap.searchvncauthbypass())
        elif not neg and param == "authhttp":
            flt = db.nmap.flt_and(flt, db.nmap.searchhttpauth())
        elif not neg and param == "banner":
            flt = db.nmap.flt_and(flt, db.nmap.searchbanner(utils.str2regexp(value)))
        elif param == "cookie":
            flt = db.nmap.flt_and(flt, db.nmap.searchcookie(value))
        elif param == "file":
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchfile())
            else:
                value = value.split(":", 1)
                if len(value) == 1:
                    flt = db.nmap.flt_and(flt, db.nmap.searchfile(fname=utils.str2regexp(value[0])))
                else:
                    flt = db.nmap.flt_and(
                        flt, db.nmap.searchfile(fname=utils.str2regexp(value[1]), scripts=value[0].split(","))
                    )
        elif not neg and param == "geovision":
            flt = db.nmap.flt_and(flt, db.nmap.searchgeovision())
        elif param == "httptitle":
            flt = db.nmap.flt_and(flt, db.nmap.searchhttptitle(utils.str2regexp(value)))
        elif not neg and param == "nfs":
            flt = db.nmap.flt_and(flt, db.nmap.searchnfs())
        elif not neg and param in ["nis", "yp"]:
            flt = db.nmap.flt_and(flt, db.nmap.searchypserv())
        elif not neg and param == "mssqlemptypwd":
            flt = db.nmap.flt_and(flt, db.nmap.searchmssqlemptypwd())
        elif not neg and param == "mysqlemptypwd":
            flt = db.nmap.flt_and(flt, db.nmap.searchmysqlemptypwd())
        elif not neg and param == "sshkey":
            if value:
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey(output=utils.str2regexp(value)))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey())
        elif not neg and param.startswith("sshkey."):
            subfield = param.split(".", 1)[1]
            if subfield in ["fingerprint", "key", "type", "bits"]:
                if subfield == "type":
                    subfield = "keytype"
                flt = db.nmap.flt_and(flt, db.nmap.searchsshkey(**{subfield: utils.str2regexp(value)}))
            else:
                add_unused(neg, param, value)
        elif not neg and param == "owa":
            flt = db.nmap.flt_and(flt, db.nmap.searchowa())
        elif param == "phpmyadmin":
            flt = db.nmap.flt_and(flt, db.nmap.searchphpmyadmin())
        elif not neg and param.startswith("smb."):
            flt = db.nmap.flt_and(flt, db.nmap.searchsmb(**{param[4:]: utils.str2regexp(value)}))
        elif not neg and param == "smbshare":
            flt = db.nmap.flt_and(flt, db.nmap.searchsmbshares(access="" if value is None else value))
        elif param == "torcert":
            flt = db.nmap.flt_and(flt, db.nmap.searchtorcert())
        elif not neg and param == "webfiles":
            flt = db.nmap.flt_and(flt, db.nmap.searchwebfiles())
        elif not neg and param == "webmin":
            flt = db.nmap.flt_and(flt, db.nmap.searchwebmin())
        elif not neg and param == "x11srv":
            flt = db.nmap.flt_and(flt, db.nmap.searchx11())
        elif not neg and param == "x11open":
            flt = db.nmap.flt_and(flt, db.nmap.searchx11access())
        elif not neg and param == "xp445":
            flt = db.nmap.flt_and(flt, db.nmap.searchxp445())
        # OS fingerprint
        elif not neg and param == "os":
            flt = db.nmap.flt_and(flt, db.nmap.searchos(utils.str2regexp(value)))
        # device types
        elif param in ["devicetype", "devtype"]:
            flt = db.nmap.flt_and(flt, db.nmap.searchdevicetype(utils.str2regexp(value)))
        elif param in ["netdev", "networkdevice"]:
            flt = db.nmap.flt_and(flt, db.nmap.searchnetdev())
        elif param == "phonedev":
            flt = db.nmap.flt_and(flt, db.nmap.searchphonedev())
        # traceroute
        elif param == "hop":
            if ":" in value:
                hop, ttl = value.split(":", 1)
                flt = db.nmap.flt_and(flt, db.nmap.searchhop(hop, ttl=int(ttl), neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchhop(value, neg=neg))
        elif param == "hopname":
            flt = db.nmap.flt_and(flt, db.nmap.searchhopname(value, neg=neg))
        elif param == "hopdomain":
            flt = db.nmap.flt_and(flt, db.nmap.searchhopdomain(value, neg=neg))
        # sort
        elif param == "sortby":
            if neg:
                sortby.append((value, -1))
            else:
                sortby.append((value, 1))
        elif param in ["open", "filtered", "closed"]:
            value = value.replace("_", "/").split(",")
            protos = {}
            for port in value:
                if "/" in port:
                    proto, port = port.split("/")
                else:
                    proto, port = "tcp", port
                protos.setdefault(proto, []).append(int(port))
            for proto, ports in protos.iteritems():
                flt = db.nmap.flt_and(
                    flt,
                    db.nmap.searchport(ports[0], protocol=proto, state=param)
                    if len(ports) == 1
                    else db.nmap.searchports(ports, protocol=proto, state=param),
                )
        elif param == "otheropenport":
            flt = db.nmap.flt_and(flt, db.nmap.searchportsother(map(int, value.split(","))))
        elif param == "screenshot":
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(neg=neg))
            elif value.isdigit():
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(port=int(value), neg=neg))
            elif value.startswith("tcp/") or value.startswith("udp/"):
                value = value.split("/", 1)
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(port=int(value[1]), protocol=value[0], neg=neg))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(service=value, neg=neg))
        elif param == "screenwords":
            if value is None:
                flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(words=not neg))
            else:
                params = value.split(":", 1)
                words = map(utils.str2regexp, params[0].split(",")) if "," in params[0] else utils.str2regexp(params[0])
                if len(params) == 1:
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(words=words, neg=neg))
                elif params[1].isdigit():
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(port=int(value), neg=neg, words=words))
                elif params[1].startswith("tcp/") or params[1].startswith("udp/"):
                    params[1] = params[1].split("/", 1)
                    flt = db.nmap.flt_and(
                        flt,
                        db.nmap.searchscreenshot(port=int(params[1][1]), protocol=params[1][0], neg=neg, words=words),
                    )
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchscreenshot(service=value, neg=neg, words=words))
        elif param == "cpe":
            if value:
                cpe_kwargs = {}
                cpe_fields = ["cpe_type", "vendor", "product", "version"]
                for field, cpe_arg in zip(cpe_fields, value.split(":", 3)):
                    cpe_kwargs[field] = utils.str2regexp(cpe_arg)
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe(**cpe_kwargs))
            else:
                flt = db.nmap.flt_and(flt, db.nmap.searchcpe())
        elif param == "display":
            # ignore this parameter
            pass
        elif value is None:
            if (
                param.startswith("tcp_")
                or param.startswith("tcp/")
                or param.startswith("udp_")
                or param.startswith("udp/")
            ):
                proto, port = param.replace("_", "/").split("/", 1)
                port = int(port)
                flt = db.nmap.flt_and(flt, db.nmap.searchport(port, protocol=proto, neg=neg))
            elif param == "openport":
                flt = db.nmap.flt_and(flt, db.nmap.searchopenport(neg=neg))
            elif param.isdigit():
                flt = db.nmap.flt_and(flt, db.nmap.searchport(int(param), neg=neg))
            elif all(x.isdigit() for x in param.split(",")):
                flt = db.nmap.flt_and(flt, db.nmap.searchports(map(int, param.split(",")), neg=neg))
            elif IPADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchhost(param, neg=neg))
            elif NETADDR.match(param):
                flt = db.nmap.flt_and(flt, db.nmap.searchnet(param, neg=neg))
            elif get_notepad_pages is not None and param == "notes":
                flt = db.nmap.flt_and(flt, db.nmap.searchhosts(get_notepad_pages(), neg=neg))
            elif "<" in param:
                param = param.split("<", 1)
                if param[1] and param[1][0] == "=":
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(param[0], int(param[1][1:]), ">" if neg else "<="))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(param[0], int(param[1]), ">=" if neg else "<"))
            elif ">" in param:
                param = param.split(">", 1)
                if param[1] and param[1][0] == "=":
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(param[0], int(param[1][1:]), "<" if neg else ">="))
                else:
                    flt = db.nmap.flt_and(flt, db.nmap.searchcmp(param[0], int(param[1]), "<=" if neg else ">"))
            else:
                add_unused(neg, param, value)
        else:
            add_unused(neg, param, value)
    return flt, archive, sortby, unused, skip, limit
예제 #6
0
파일: utils.py 프로젝트: ivre/ivre
def flt_from_query(dbase, query, base_flt=None):
    """Return a tuple (`flt`, `sortby`, `unused`, `skip`, `limit`, `fields`):

    - a filter based on the query

    - a list of [`key`, `order`] to sort results

    - a list of the unused elements of the query (errors)

    - an integer for the number of results to skip

    - an integer for the maximum number of results to return

    """
    unused = []
    sortby = []
    skip = 0
    limit = None
    fields = None
    flt = get_init_flt(dbase) if base_flt is None else base_flt

    def add_unused(neg, param, value):
        """Add to the `unused` list a string representing (neg, param,
        value).

        """
        unused.append("%s%s" % (
            "-" if neg else "",
            "%s=%s" % (param, value) if value is not None else param,
        ))

    for (neg, param, value) in query:
        if not neg and param == "skip":
            skip = int(value)
        elif not neg and param == "limit":
            limit = int(value)
        elif not neg and param == "fields":
            fields = value.split(",")
        elif param == "id":
            flt = dbase.flt_and(
                flt,
                dbase.searchobjectid(value.replace("-", ",").split(","),
                                     neg=neg))
        elif param == "host":
            flt = dbase.flt_and(flt, dbase.searchhost(value, neg=neg))
        elif param == "net":
            flt = dbase.flt_and(flt, dbase.searchnet(value, neg=neg))
        elif param == "range":
            flt = dbase.flt_and(
                flt,
                dbase.searchrange(*value.replace("-", ",").split(",", 1),
                                  neg=neg))
        elif param == "countports":
            vals = [int(val) for val in value.replace("-", ",").split(",", 1)]
            if len(vals) == 1:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchcountopenports(minn=vals[0],
                                               maxn=vals[0],
                                               neg=neg))
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchcountopenports(minn=vals[0],
                                               maxn=vals[1],
                                               neg=neg))
        elif param == "hostname":
            flt = dbase.flt_and(
                flt, dbase.searchhostname(utils.str2regexp(value), neg=neg))
        elif param == "domain":
            flt = dbase.flt_and(
                flt, dbase.searchdomain(utils.str2regexp(value), neg=neg))
        elif param == "category":
            flt = dbase.flt_and(
                flt, dbase.searchcategory(utils.str2regexp(value), neg=neg))
        elif param == "country":
            flt = dbase.flt_and(
                flt, dbase.searchcountry(utils.str2list(value.upper()),
                                         neg=neg))
        elif param == "city":
            flt = dbase.flt_and(
                flt, dbase.searchcity(utils.str2regexp(value), neg=neg))
        elif param == "asnum":
            flt = dbase.flt_and(
                flt, dbase.searchasnum(utils.str2list(value), neg=neg))
        elif param == "asname":
            flt = dbase.flt_and(
                flt, dbase.searchasname(utils.str2regexp(value), neg=neg))
        elif param == "source":
            flt = dbase.flt_and(
                flt, dbase.searchsource(utils.str2regexp(value), neg=neg))
        elif param == "timerange":
            flt = dbase.flt_and(
                flt,
                dbase.searchtimerange(
                    *(float(val)
                      for val in value.replace("-", ",").split(",")),
                    neg=neg),
            )
        elif param == "timeago":
            if value and value[-1].isalpha():
                unit = {
                    "s": 1,
                    "m": 60,
                    "h": 3600,
                    "d": 86400,
                    "y": 31557600,
                }[value[-1]]
                timeago = int(value[:-1]) * unit
            else:
                timeago = int(value)
            flt = dbase.flt_and(
                flt,
                dbase.searchtimeago(datetime.timedelta(0, timeago), neg=neg))
        elif not neg and param == "service":
            if ":" in value:
                req, port = value.split(":", 1)
                port = int(port)
                flt = dbase.flt_and(
                    flt,
                    dbase.searchservice(utils.str2regexpnone(req), port=port))
            else:
                flt = dbase.flt_and(
                    flt, dbase.searchservice(utils.str2regexpnone(value)))
        elif not neg and param == "product" and ":" in value:
            product = value.split(":", 2)
            if len(product) == 2:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchproduct(
                        product=utils.str2regexpnone(product[1]),
                        service=utils.str2regexpnone(product[0]),
                    ),
                )
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchproduct(
                        product=utils.str2regexpnone(product[1]),
                        service=utils.str2regexpnone(product[0]),
                        port=int(product[2]),
                    ),
                )
        elif not neg and param == "version" and value.count(":") >= 2:
            product = value.split(":", 3)
            if len(product) == 3:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchproduct(
                        product=utils.str2regexpnone(product[1]),
                        version=utils.str2regexpnone(product[2]),
                        service=utils.str2regexpnone(product[0]),
                    ),
                )
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchproduct(
                        product=utils.str2regexpnone(product[1]),
                        version=utils.str2regexpnone(product[2]),
                        service=utils.str2regexpnone(product[0]),
                        port=int(product[3]),
                    ),
                )
        elif param == "script":
            value = value.split(":", 1)
            if len(value) == 1:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchscript(name=utils.str2regexp(value[0]),
                                       neg=neg),
                )
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchscript(
                        name=utils.str2regexp(value[0]),
                        output=utils.str2regexp(value[1]),
                        neg=neg,
                    ),
                )
        # results of scripts or version scans
        elif not neg and param == "anonftp":
            flt = dbase.flt_and(flt, dbase.searchftpanon())
        elif not neg and param == "anonldap":
            flt = dbase.flt_and(flt, dbase.searchldapanon())
        elif not neg and param == "authbypassvnc":
            flt = dbase.flt_and(flt, dbase.searchvncauthbypass())
        elif not neg and param == "authhttp":
            flt = dbase.flt_and(flt, dbase.searchhttpauth())
        elif not neg and param == "banner":
            flt = dbase.flt_and(flt,
                                dbase.searchbanner(utils.str2regexp(value)))
        elif param == "cookie":
            flt = dbase.flt_and(flt, dbase.searchcookie(value))
        elif param == "file":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchfile())
            else:
                value = value.split(":", 1)
                if len(value) == 1:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchfile(fname=utils.str2regexp(value[0])))
                else:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchfile(
                            fname=utils.str2regexp(value[1]),
                            scripts=value[0].split(","),
                        ),
                    )
        elif param == "vuln":
            try:
                vulnid, status = value.split(":", 1)
            except ValueError:
                vulnid = value
                status = None
            except AttributeError:
                vulnid = None
                status = None
            flt = dbase.flt_and(flt,
                                dbase.searchvuln(vulnid=vulnid, status=status))
        elif not neg and param == "geovision":
            flt = dbase.flt_and(flt, dbase.searchgeovision())
        elif param == "httptitle":
            flt = dbase.flt_and(flt,
                                dbase.searchhttptitle(utils.str2regexp(value)))
        elif not neg and param == "nfs":
            flt = dbase.flt_and(flt, dbase.searchnfs())
        elif not neg and param in ["nis", "yp"]:
            flt = dbase.flt_and(flt, dbase.searchypserv())
        elif not neg and param == "mssqlemptypwd":
            flt = dbase.flt_and(flt, dbase.searchmssqlemptypwd())
        elif not neg and param == "mysqlemptypwd":
            flt = dbase.flt_and(flt, dbase.searchmysqlemptypwd())
        elif not neg and param == "sshkey":
            if value:
                flt = dbase.flt_and(
                    flt, dbase.searchsshkey(output=utils.str2regexp(value)))
            else:
                flt = dbase.flt_and(flt, dbase.searchsshkey())
        elif not neg and param.startswith("sshkey."):
            subfield = param.split(".", 1)[1]
            if subfield in ["fingerprint", "key", "type", "bits"]:
                if subfield == "type":
                    subfield = "keytype"
                elif subfield == "bits":
                    try:
                        value = int(value)
                    except (ValueError, TypeError):
                        pass
                else:
                    value = utils.str2regexp(value)
                flt = dbase.flt_and(flt,
                                    dbase.searchsshkey(**{subfield: value}))
            else:
                add_unused(neg, param, value)
        elif not neg and param == "cert":
            flt = dbase.flt_and(flt, dbase.searchcert())
        elif param.startswith("cert."):
            subfield = param.split(".", 1)[1]
            if subfield == "self_signed" and value is None:
                flt = dbase.flt_and(flt, dbase.searchcert(self_signed=not neg))
            elif not neg:
                if subfield in ["md5", "sha1", "sha256", "subject", "issuer"]:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcert(**{
                            subfield: utils.str2regexp(value),
                        }),
                    )
                elif subfield in [
                        "pubkey.md5", "pubkey.sha1", "pubkey.sha256"
                ]:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcert(
                            **{
                                "pk%s" % subfield[7:]: utils.str2regexp(value),
                            }),
                    )
                else:
                    add_unused(neg, param, value)
            else:
                add_unused(neg, param, value)
        elif not neg and param == "httphdr":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchhttphdr())
            elif ":" in value:
                name, value = value.split(":", 1)
                name = utils.str2regexp(name.lower())
                value = utils.str2regexp(value)
                flt = dbase.flt_and(
                    flt, dbase.searchhttphdr(name=name, value=value))
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchhttphdr(name=utils.str2regexp(value.lower())))
        elif not neg and param == "httpapp":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchhttpapp())
            elif ":" in value:
                name, version = (utils.str2regexp(string)
                                 for string in value.split(":", 1))
                flt = dbase.flt_and(
                    flt, dbase.searchhttpapp(name=name, version=version))
            else:
                flt = dbase.flt_and(
                    flt, dbase.searchhttpapp(name=utils.str2regexp(value)))
        elif not neg and param == "owa":
            flt = dbase.flt_and(flt, dbase.searchowa())
        elif param == "phpmyadmin":
            flt = dbase.flt_and(flt, dbase.searchphpmyadmin())
        elif not neg and param.startswith("smb."):
            flt = dbase.flt_and(
                flt, dbase.searchsmb(**{param[4:]: utils.str2regexp(value)}))
        elif not neg and param.startswith("ntlm."):
            key = {
                "name": "Target_Name",
                "server": "NetBIOS_Computer_Name",
                "domain": "NetBIOS_Domain_Name",
                "workgroup": "Workgroup",
                "domain_dns": "DNS_Domain_Name",
                "forest": "DNS_Tree_Name",
                "fqdn": "DNS_Computer_Name",
                "os": "Product_Version",
                "version": "NTLM_Version",
            }
            flt = dbase.flt_and(
                flt,
                dbase.searchntlm(
                    **{key.get(param[5:], param[5:]): utils.str2regexp(value)
                       }),
            )
        elif not neg and param == "smbshare":
            flt = dbase.flt_and(
                flt,
                dbase.searchsmbshares(access="" if value is None else value),
            )
        elif param == "torcert":
            flt = dbase.flt_and(flt, dbase.searchtorcert())
        elif not neg and param == "webfiles":
            flt = dbase.flt_and(flt, dbase.searchwebfiles())
        elif not neg and param == "webmin":
            flt = dbase.flt_and(flt, dbase.searchwebmin())
        elif not neg and param == "x11srv":
            flt = dbase.flt_and(flt, dbase.searchx11())
        elif not neg and param == "x11open":
            flt = dbase.flt_and(flt, dbase.searchx11access())
        elif not neg and param == "xp445":
            flt = dbase.flt_and(flt, dbase.searchxp445())
        elif param == "ssl-ja3-client":
            flt = dbase.flt_and(
                flt,
                dbase.searchja3client(
                    value_or_hash=(None if value is None else
                                   utils.str2regexp(value)),
                    neg=neg,
                ),
            )
        elif param == "ssl-ja3-server":
            if value is None:
                # There are no additional arguments
                flt = dbase.flt_and(flt, dbase.searchja3server(neg=neg))
            else:
                split = [
                    utils.str2regexp(v) if v else None
                    for v in value.split(":", 1)
                ]
                if len(split) == 1:
                    # Only a JA3 server is given
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchja3server(
                            value_or_hash=(split[0]),
                            neg=neg,
                        ),
                    )
                else:
                    # Both client and server JA3 are specified
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchja3server(
                            value_or_hash=split[0],
                            client_value_or_hash=split[1],
                            neg=neg,
                        ),
                    )
        elif param == "ssl-jarm":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchjarm(neg=neg))
            else:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchjarm(value=utils.str2regexp(value), neg=neg))
        elif param in {"hassh", "hassh-client", "hassh-server"}:
            server = {
                "hassh": None,
                "hassh-client": False,
                "hassh-server": True
            }[param]
            flt = dbase.flt_and(
                flt,
                dbase.searchhassh(
                    value_or_hash=(None if value is None else
                                   utils.str2regexp(value)),
                    server=server,
                ),
            )
        elif param == "useragent":
            if value:
                flt = dbase.flt_and(
                    flt,
                    dbase.searchuseragent(useragent=utils.str2regexp(value)))
            else:
                flt = dbase.flt_and(flt, dbase.searchuseragent())
        # OS fingerprint
        elif not neg and param == "os":
            flt = dbase.flt_and(flt, dbase.searchos(utils.str2regexp(value)))
        # device types
        elif param in ["devicetype", "devtype"]:
            flt = dbase.flt_and(
                flt, dbase.searchdevicetype(utils.str2regexp(value)))
        elif param in ["netdev", "networkdevice"]:
            flt = dbase.flt_and(flt, dbase.searchnetdev())
        elif param == "phonedev":
            flt = dbase.flt_and(flt, dbase.searchphonedev())
        # traceroute
        elif param == "hop":
            if ":" in value:
                hop, ttl = value.split(":", 1)
                flt = dbase.flt_and(
                    flt, dbase.searchhop(hop, ttl=int(ttl), neg=neg))
            else:
                flt = dbase.flt_and(flt, dbase.searchhop(value, neg=neg))
        elif param == "hopname":
            flt = dbase.flt_and(flt, dbase.searchhopname(value, neg=neg))
        elif param == "hopdomain":
            flt = dbase.flt_and(flt, dbase.searchhopdomain(value, neg=neg))
        elif not neg and param in [
                "ike.vendor_id.name", "ike.vendor_id.value"
        ]:
            flt = dbase.flt_and(
                flt,
                dbase.searchscript(
                    name="ike-info",
                    values={
                        "vendor_ids.%s" % param[14:]: utils.str2regexp(value)
                    },
                ),
            )
        elif not neg and param == "ike.notification":
            flt = dbase.flt_and(
                flt,
                dbase.searchscript(
                    name="ike-info",
                    values={"notification_type": utils.str2regexp(value)},
                ),
            )
        # sort
        elif param == "sortby":
            if neg:
                sortby.append((value, -1))
            else:
                sortby.append((value, 1))
        elif param in ["open", "filtered", "closed"]:
            value = value.replace("_", "/").split(",")
            protos = {}
            for port in value:
                if "/" in port:
                    proto, port = port.split("/")
                else:
                    proto = "tcp"
                protos.setdefault(proto, []).append(int(port))
            for proto, ports in protos.items():
                flt = dbase.flt_and(
                    flt,
                    dbase.searchport(ports[0], protocol=proto, state=param)
                    if len(ports) == 1 else dbase.searchports(
                        ports, protocol=proto, state=param),
                )
        elif param == "otheropenport":
            flt = dbase.flt_and(
                flt,
                dbase.searchportsother([int(val) for val in value.split(",")]))
        elif param == "screenshot":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchscreenshot(neg=neg))
            elif value.isdigit():
                flt = dbase.flt_and(
                    flt, dbase.searchscreenshot(port=int(value), neg=neg))
            elif value.startswith("tcp/") or value.startswith("udp/"):
                value = value.split("/", 1)
                flt = dbase.flt_and(
                    flt,
                    dbase.searchscreenshot(port=int(value[1]),
                                           protocol=value[0],
                                           neg=neg),
                )
            else:
                flt = dbase.flt_and(
                    flt, dbase.searchscreenshot(service=value, neg=neg))
        elif param == "screenwords":
            if value is None:
                flt = dbase.flt_and(flt, dbase.searchscreenshot(words=not neg))
            else:
                params = value.split(":", 1)
                words = ([
                    utils.str2regexp(elt) for elt in params[0].split(",")
                ] if "," in params[0] else utils.str2regexp(params[0]))
                if len(params) == 1:
                    flt = dbase.flt_and(
                        flt, dbase.searchscreenshot(words=words, neg=neg))
                elif params[1].isdigit():
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchscreenshot(port=int(value),
                                               neg=neg,
                                               words=words),
                    )
                elif params[1].startswith("tcp/") or params[1].startswith(
                        "udp/"):
                    params[1] = params[1].split("/", 1)
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchscreenshot(
                            port=int(params[1][1]),
                            protocol=params[1][0],
                            neg=neg,
                            words=words,
                        ),
                    )
                else:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchscreenshot(service=value,
                                               neg=neg,
                                               words=words))
        elif param == "cpe":
            if value:
                cpe_kwargs = {}
                cpe_fields = ["cpe_type", "vendor", "product", "version"]
                for field, cpe_arg in zip(cpe_fields, value.split(":", 3)):
                    cpe_kwargs[field] = utils.str2regexp(cpe_arg)
                flt = dbase.flt_and(flt, dbase.searchcpe(**cpe_kwargs))
            else:
                flt = dbase.flt_and(flt, dbase.searchcpe())
        elif param == "tag":
            if value:
                if ":" in value:
                    tag_val, tag_info = value.split(":", 1)
                    tag = {}
                    if tag_val:
                        tag["value"] = utils.str2regexp(tag_val)
                    if tag_info:
                        tag["info"] = utils.str2regexp(tag_info)
                    flt = dbase.flt_and(flt, dbase.searchtag(tag, neg=neg))
                else:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchtag({"value": utils.str2regexp(value)},
                                        neg=neg),
                    )
            else:
                flt = dbase.flt_and(flt, dbase.searchtag(neg=neg))
        elif param == "search":
            try:
                flt = dbase.flt_and(flt, dbase.searchtext(value))
            except AttributeError:  # .searchtext() only exists in MongoDB
                add_unused(neg, param, value)
        elif param == "display":
            # ignore this parameter
            pass
        elif value is None:
            if PORT.search(param) is not None:
                # Python >= 3.8: if (match := PORT.search(param)) is not None
                proto, port = PORT.search(param).groups()
                flt = dbase.flt_and(
                    flt,
                    dbase.searchport(int(port),
                                     protocol=proto or "tcp",
                                     neg=neg))
            elif param == "openport":
                flt = dbase.flt_and(flt, dbase.searchopenport(neg=neg))
            elif param == "ipv4":
                if neg:
                    flt = dbase.flt_and(flt, dbase.searchipv6())
                else:
                    flt = dbase.flt_and(flt, dbase.searchipv4())
            elif param == "ipv6":
                if neg:
                    flt = dbase.flt_and(flt, dbase.searchipv4())
                else:
                    flt = dbase.flt_and(flt, dbase.searchipv6())
            elif all(PORT.search(x) is not None for x in param.split(",")):
                proto_ports = {}
                for port in param.split(","):
                    proto, port = PORT.search(port).groups()
                    proto_ports.setdefault(proto or "tcp",
                                           set()).add(int(port))
                for proto, ports in proto_ports.items():
                    if len(ports) > 1:
                        flt = dbase.flt_and(
                            flt,
                            dbase.searchports(list(ports),
                                              protocol=proto,
                                              neg=neg),
                        )
                    else:
                        flt = dbase.flt_and(
                            flt,
                            dbase.searchport(next(iter(ports)),
                                             protocol=proto,
                                             neg=neg),
                        )
            elif utils.IPADDR.search(param):
                flt = dbase.flt_and(flt, dbase.searchhost(param, neg=neg))
            elif utils.NETADDR.search(param):
                flt = dbase.flt_and(flt, dbase.searchnet(param, neg=neg))
            elif get_notepad_pages is not None and param == "notes":
                flt = dbase.flt_and(
                    flt, dbase.searchhosts(get_notepad_pages(), neg=neg))
            elif "<" in param:
                param = param.split("<", 1)
                if param[1] and param[1][0] == "=":
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcmp(param[0], int(param[1][1:]),
                                        ">" if neg else "<="),
                    )
                else:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcmp(param[0], int(param[1]),
                                        ">=" if neg else "<"),
                    )
            elif ">" in param:
                param = param.split(">", 1)
                if param[1] and param[1][0] == "=":
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcmp(param[0], int(param[1][1:]),
                                        "<" if neg else ">="),
                    )
                else:
                    flt = dbase.flt_and(
                        flt,
                        dbase.searchcmp(param[0], int(param[1]),
                                        "<=" if neg else ">"),
                    )
            else:
                add_unused(neg, param, value)
        else:
            add_unused(neg, param, value)
    return flt, sortby, unused, skip, limit, fields