Exemple #1
0
def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "ips_or_macs",
        nargs="*",
        help=("Display results for specified IP (or networks) or MAC addresses"
              " (or MAC address regexps)."),
    )
    parser.add_argument("-s", "--sensor")
    parser.add_argument("-c", "--count", action="store_true")
    parser.add_argument("-r",
                        "--resolve",
                        action="store_true",
                        help="Resolve MAC manufacturer")
    args = parser.parse_args()
    flts = ([], [])  # MAC & IP filters
    for arg in args.ips_or_macs:
        if arg[:1] in "-!~":
            neg = True
            arg = arg[1:]
        else:
            neg = False
        match = MAC_ADDR.search(arg)
        if match:
            flts[0].append(db.passive.searchmac(mac=arg, neg=neg))
        elif arg.startswith("/") and "/" in arg[1:]:
            flts[0].append(
                db.passive.searchmac(mac=utils.str2regexp(arg), neg=neg))
        elif "/" in arg:
            flts[1].append(db.passive.searchnet(arg, neg=neg))
        else:
            flts[1].append(db.passive.searchhost(arg, neg=neg))
    if not flts[0]:
        flts[0].append(db.passive.searchmac())
    flt = db.passive.flt_or(*flts[0])
    if flts[1]:
        flt = db.passive.flt_and(flt, db.passive.flt_or(*flts[1]))
    if args.sensor is not None:
        flt = db.passive.flt_and(flt, db.passive.searchsensor(args.sensor))
    if args.count:
        print(db.passive.count(flt))
        return
    for rec in db.passive.get(flt,
                              sort=[("addr", 1), ("value", 1), ("source", 1)]):
        rec["times"] = "s" if rec["count"] > 1 else ""
        if not rec.get("sensor"):
            rec["sensor"] = "-"
        if args.resolve:
            try:
                manuf = utils.mac2manuf(rec["value"])[0]
            except (TypeError, ValueError):
                pass
            else:
                rec["value"] = "%s (%s)" % (rec["value"], manuf)
        print("%(addr)s at %(value)s on %(sensor)s (%(source)s %(count)s "
              "time%(times)s, %(firstseen)s - %(lastseen)s)" % rec)
Exemple #2
0
def get_nmap(subdb):
    """Get records from Nmap & View databases

    :param str subdb: database to query (must be "scans" or "view")
    :query str q: query (including limit/skip and sort)
    :query str f: filter
    :query str callback: callback to use for JSONP results
    :query bool ipsasnumbers: to get IP addresses as numbers rather than as
                             strings
    :query bool datesasstrings: to get dates as strings rather than as
                               timestamps
    :query str format: "json" (the default) or "ndjson"
    :status 200: no error
    :status 400: invalid referer
    :>jsonarr object: results

    """
    subdb_tool = "view" if subdb == "view" else "scancli"
    subdb = db.view if subdb == "view" else db.nmap
    flt_params = get_base(subdb)
    # PostgreSQL: the query plan if affected by the limit and gives
    # really poor results. This is a temporary workaround (look for
    # XXX-WORKAROUND-PGSQL).
    # result = subdb.get(flt_params.flt, limit=flt_params.limit,
    #                    skip=flt_params.skip, sort=flt_params.sortby)
    result = subdb.get(
        flt_params.flt,
        skip=flt_params.skip,
        sort=flt_params.sortby,
        fields=flt_params.fields,
    )

    if flt_params.unused:
        msg = "Option%s not understood: %s" % (
            "s" if len(flt_params.unused) > 1 else "",
            ", ".join(flt_params.unused),
        )
        if flt_params.callback is not None:
            yield webutils.js_alert("param-unused", "warning", msg)
        utils.LOGGER.warning(msg)
    elif flt_params.callback is not None:
        yield webutils.js_del_alert("param-unused")

    if config.DEBUG:
        msg1 = "filter: %r" % subdb.flt2str(flt_params.flt)
        msg2 = "user: %r" % webutils.get_user()
        utils.LOGGER.debug(msg1)
        utils.LOGGER.debug(msg2)
        if flt_params.callback is not None:
            yield webutils.js_alert("filter", "info", msg1)
            yield webutils.js_alert("user", "info", msg2)

    version_mismatch = {}
    if flt_params.callback is None:
        if flt_params.fmt == "json":
            yield "[\n"
    else:
        yield "%s([\n" % flt_params.callback
    # XXX-WORKAROUND-PGSQL
    # for rec in result:
    for i, rec in enumerate(result):
        for fld in ["_id", "scanid"]:
            try:
                del rec[fld]
            except KeyError:
                pass
        if flt_params.ipsasnumbers:
            rec["addr"] = utils.force_ip2int(rec["addr"])
        if not flt_params.datesasstrings:
            for field in subdb.datetime_fields:
                _set_datetime_field(subdb, rec, field)
        for port in rec.get("ports", []):
            if "screendata" in port:
                port["screendata"] = utils.encode_b64(port["screendata"])
            for script in port.get("scripts", []):
                if "masscan" in script:
                    try:
                        del script["masscan"]["raw"]
                    except KeyError:
                        pass
        if not flt_params.ipsasnumbers:
            if "traces" in rec:
                for trace in rec["traces"]:
                    trace["hops"].sort(key=lambda x: x["ttl"])
                    for hop in trace["hops"]:
                        hop["ipaddr"] = utils.force_int2ip(hop["ipaddr"])
        addresses = rec.get("addresses", {}).get("mac")
        if addresses:
            newaddresses = []
            for addr in addresses:
                manuf = utils.mac2manuf(addr)
                if manuf and manuf[0]:
                    newaddresses.append({"addr": addr, "manuf": manuf[0]})
                else:
                    newaddresses.append({"addr": addr})
            rec["addresses"]["mac"] = newaddresses
        if flt_params.fmt == "ndjson":
            yield "%s\n" % json.dumps(rec, default=utils.serialize)
        else:
            yield "%s\t%s" % (
                "" if i == 0 else ",\n",
                json.dumps(rec, default=utils.serialize),
            )
        check = subdb.cmp_schema_version_host(rec)
        if check:
            version_mismatch[check] = version_mismatch.get(check, 0) + 1
        # XXX-WORKAROUND-PGSQL
        if flt_params.limit and i + 1 >= flt_params.limit:
            break
    if flt_params.callback is None:
        if flt_params.fmt == "json":
            yield "\n]\n"
    else:
        yield "\n]);\n"

    messages = {
        1:
        lambda count: ("%d document%s displayed %s out-of-date. Please run "
                       "the following command: 'ivre %s "
                       "--update-schema;" % (
                           count,
                           "s" if count > 1 else "",
                           "are" if count > 1 else "is",
                           subdb_tool,
                       )),
        -1:
        lambda count: ("%d document%s displayed ha%s been inserted by "
                       "a more recent version of IVRE. Please update "
                       "IVRE!" % (count, "s" if count > 1 else "", "ve"
                                  if count > 1 else "s")),
    }
    for mismatch, count in version_mismatch.items():
        message = messages[mismatch](count)
        if flt_params.callback is not None:
            yield webutils.js_alert(
                "version-mismatch-%d" % ((mismatch + 1) // 2), "warning",
                message)
        utils.LOGGER.warning(message)
Exemple #3
0
def _display_xml_host(h, out=sys.stdout):
    out.write('<host')
    for k in ["timedout", "timeoutcounter"]:
        if k in h:
            out.write(' %s=%s' % (k, saxutils.quoteattr(h[k])))
    for k in ["starttime", "endtime"]:
        if k in h:
            out.write(' %s=%s' % (k, saxutils.quoteattr(h[k].strftime('%s'))))
    out.write('>')
    if 'state' in h:
        out.write('<status state="%s"' % h['state'])
        for k in ["reason", "reason_ttl"]:
            kk = "state_%s" % k
            if kk in h:
                out.write(' %s="%s"' % (k, h[kk]))
        out.write('/>')
    out.write('\n')
    if 'addr' in h:
        out.write('<address addr="%s" addrtype="ipv%d"/>\n' % (
            h['addr'],
            6 if ':' in h['addr'] else 4,
        ))
    for atype, addrs in viewitems(h.get('addresses', {})):
        for addr in addrs:
            extra = ""
            if atype == "mac":
                manuf = utils.mac2manuf(addr)
                # if manuf:
                #     if len(manuf) > 1 and manuf[1]:
                #         manuf = manuf[1]
                #     else:
                #         manuf = manuf[0]
                #     extra = ' vendor=%s' % saxutils.quoteattr(manuf[0])
                if manuf and manuf[0]:
                    extra = ' vendor=%s' % saxutils.quoteattr(manuf[0])
            out.write('<address addr="%s" addrtype="%s"%s/>\n' %
                      (addr, atype, extra))
    if 'hostnames' in h:
        out.write('<hostnames>\n')
        for hostname in h['hostnames']:
            out.write('<hostname')
            for k in ['name', 'type']:
                if k in hostname:
                    out.write(' %s="%s"' % (k, hostname[k]))
            out.write('/>\n')
        out.write('</hostnames>\n')
    out.write('<ports>')
    for state, counts in viewitems(h.get('extraports', {})):
        out.write('<extraports state="%s" count="%d">\n' %
                  (state, counts['total']))
        for reason, count in viewitems(counts['reasons']):
            out.write('<extrareasons reason="%s" count="%d"/>\n' %
                      (reason, count))
        out.write('</extraports>\n')
    for p in h.get('ports', []):
        if p.get('port') == -1:
            h['scripts'] = p['scripts']
            continue
        out.write('<port')
        if 'protocol' in p:
            out.write(' protocol="%s"' % p['protocol'])
        if 'port' in p:
            out.write(' portid="%s"' % p['port'])
        out.write('><state')
        for k in ['state', 'reason', 'reason_ttl']:
            kk = 'state_%s' % k
            if kk in p:
                out.write(' %s=%s' % (k, saxutils.quoteattr(str(p[kk]))))
        out.write('/>')
        if 'service_name' in p:
            out.write('<service name="%s"' % p['service_name'])
            for k in [
                    'servicefp', 'product', 'version', 'extrainfo', 'ostype',
                    'method', 'conf'
            ]:
                kk = "service_%s" % k
                if kk in p:
                    if isinstance(p[kk], basestring):
                        out.write(' %s=%s' % (k, saxutils.quoteattr(p[kk])))
                    else:
                        out.write(' %s="%s"' % (k, p[kk]))
            # TODO: CPE
            out.write('></service>')
        for s in p.get('scripts', []):
            _display_xml_script(s, out=out)
        out.write('</port>\n')
    out.write('</ports>\n')
    if 'scripts' in h:
        out.write('<hostscript>')
        for s in h['scripts']:
            _display_xml_script(s, out=out)
        out.write('</hostscript>')
    for trace in h.get('traces', []):
        out.write('<trace')
        if 'port' in trace:
            out.write(' port=%s' % (saxutils.quoteattr(str(trace['port']))))
        if 'protocol' in trace:
            out.write(' proto=%s' % (saxutils.quoteattr(trace['protocol'])))
        out.write('>\n')
        for hop in sorted(trace.get('hops', []), key=lambda hop: hop['ttl']):
            out.write('<hop')
            if 'ttl' in hop:
                out.write(' ttl=%s' % (saxutils.quoteattr(str(hop['ttl']))))
            if 'ipaddr' in hop:
                out.write(' ipaddr=%s' % (saxutils.quoteattr(hop['ipaddr'])))
            if 'rtt' in hop:
                out.write(
                    ' rtt=%s' %
                    (saxutils.quoteattr('%.2f' % hop['rtt'] if isinstance(
                        hop['rtt'], float) else hop['rtt'])))
            if 'host' in hop:
                out.write(' host=%s' % (saxutils.quoteattr(hop['host'])))
            out.write('/>\n')
        out.write('</trace>\n')
    out.write('</host>\n')
Exemple #4
0
def get_nmap(subdb):
    """Get records from Nmap & View databases

    :param str subdb: database to query (must be "scans" or "view")
    :query str q: query (including limit/skip and sort)
    :query str callback: callback to use for JSONP results
    :query bool ipsasnumbers: to get IP addresses as numbers rather than as
                             strings
    :query bool datesasstrings: to get dates as strings rather than as
                               timestamps
    :status 200: no error
    :status 400: invalid referer
    :>jsonarr object: results

    """
    subdb_tool = "view" if subdb == 'view' else "scancli"
    subdb = db.view if subdb == 'view' else db.nmap
    flt_params = get_nmap_base(subdb)
    # PostgreSQL: the query plan if affected by the limit and gives
    # really poor results. This is a temporary workaround (look for
    # XXX-WORKAROUND-PGSQL).
    # result = subdb.get(flt_params.flt, limit=flt_params.limit,
    #                    skip=flt_params.skip, sort=flt_params.sortby)
    result = subdb.get(flt_params.flt,
                       skip=flt_params.skip,
                       sort=flt_params.sortby)

    if flt_params.unused:
        msg = 'Option%s not understood: %s' % (
            's' if len(flt_params.unused) > 1 else '',
            ', '.join(flt_params.unused),
        )
        if flt_params.callback is not None:
            yield webutils.js_alert("param-unused", "warning", msg)
        utils.LOGGER.warning(msg)
    elif flt_params.callback is not None:
        yield webutils.js_del_alert("param-unused")

    if config.DEBUG:
        msg1 = "filter: %s" % subdb.flt2str(flt_params.flt)
        msg2 = "user: %r" % webutils.get_user()
        utils.LOGGER.debug(msg1)
        utils.LOGGER.debug(msg2)
        if flt_params.callback is not None:
            yield webutils.js_alert("filter", "info", msg1)
            yield webutils.js_alert("user", "info", msg2)

    version_mismatch = {}
    if flt_params.callback is None:
        yield "[\n"
    else:
        yield "%s([\n" % flt_params.callback
    # XXX-WORKAROUND-PGSQL
    # for rec in result:
    for i, rec in enumerate(result):
        for fld in ['_id', 'scanid']:
            try:
                del rec[fld]
            except KeyError:
                pass
        if not flt_params.ipsasnumbers:
            rec['addr'] = utils.force_int2ip(rec['addr'])
        for field in ['starttime', 'endtime']:
            if field in rec:
                if not flt_params.datesasstrings:
                    rec[field] = int(utils.datetime2timestamp(rec[field]))
        for port in rec.get('ports', []):
            if 'screendata' in port:
                port['screendata'] = utils.encode_b64(port['screendata'])
            for script in port.get('scripts', []):
                if "masscan" in script:
                    try:
                        del script['masscan']['raw']
                    except KeyError:
                        pass
        if not flt_params.ipsasnumbers:
            if 'traces' in rec:
                for trace in rec['traces']:
                    trace['hops'].sort(key=lambda x: x['ttl'])
                    for hop in trace['hops']:
                        hop['ipaddr'] = utils.force_int2ip(hop['ipaddr'])
        addresses = rec.get('addresses', {}).get('mac')
        if addresses:
            newaddresses = []
            for addr in addresses:
                manuf = utils.mac2manuf(addr)
                if manuf and manuf[0]:
                    newaddresses.append({'addr': addr, 'manuf': manuf[0]})
                else:
                    newaddresses.append({'addr': addr})
            rec['addresses']['mac'] = newaddresses
        yield "%s\t%s" % ('' if i == 0 else ',\n',
                          json.dumps(rec, default=utils.serialize))
        check = subdb.cmp_schema_version_host(rec)
        if check:
            version_mismatch[check] = version_mismatch.get(check, 0) + 1
        # XXX-WORKAROUND-PGSQL
        if i + 1 >= flt_params.limit:
            break
    if flt_params.callback is None:
        yield "\n]\n"
    else:
        yield "\n]);\n"

    messages = {
        1:
        lambda count: ("%d document%s displayed %s out-of-date. Please run "
                       "the following command: 'ivre %s "
                       "--update-schema;" %
                       (count, 's' if count > 1 else '', 'are'
                        if count > 1 else 'is', subdb_tool)),
        -1:
        lambda count: ('%d document%s displayed ha%s been inserted by '
                       'a more recent version of IVRE. Please update '
                       'IVRE!' % (count, 's' if count > 1 else '', 've'
                                  if count > 1 else 's')),
    }
    for mismatch, count in viewitems(version_mismatch):
        message = messages[mismatch](count)
        if flt_params.callback is not None:
            yield webutils.js_alert(
                "version-mismatch-%d" % ((mismatch + 1) // 2), "warning",
                message)
        utils.LOGGER.warning(message)
Exemple #5
0
def _display_xml_host(host: NmapHost, out: TextIO = sys.stdout) -> None:
    out.write("<host")
    for k in ["timedout", "timeoutcounter"]:
        if k in host:
            out.write(" %s=%s" % (k, saxutils.quoteattr(host[k])))
    for k in ["starttime", "endtime"]:
        if k in host:
            out.write(" %s=%s" %
                      (k, saxutils.quoteattr(host[k].strftime("%s"))))
    out.write(">")
    if "state" in host:
        out.write('<status state="%s"' % host["state"])
        for k in ["reason", "reason_ttl"]:
            kk = "state_%s" % k
            if kk in host:
                out.write(' %s="%s"' % (k, host[kk]))
        out.write("/>")
    out.write("\n")
    if "addr" in host:
        out.write('<address addr="%s" addrtype="ipv%d"/>\n' % (
            host["addr"],
            6 if ":" in host["addr"] else 4,
        ))
    for atype, addrs in host.get("addresses", {}).items():
        for addr in addrs:
            extra = ""
            if atype == "mac":
                manuf = utils.mac2manuf(addr)
                # if manuf:
                #     if len(manuf) > 1 and manuf[1]:
                #         manuf = manuf[1]
                #     else:
                #         manuf = manuf[0]
                #     extra = ' vendor=%s' % saxutils.quoteattr(manuf[0])
                if manuf and manuf[0]:
                    extra = " vendor=%s" % saxutils.quoteattr(manuf[0])
            out.write('<address addr="%s" addrtype="%s"%s/>\n' %
                      (addr, atype, extra))
    if "hostnames" in host:
        out.write("<hostnames>\n")
        for hostname in host["hostnames"]:
            out.write("<hostname")
            for k in ["name", "type"]:
                if k in hostname:
                    out.write(' %s="%s"' % (k, hostname[k]))
            out.write("/>\n")
        out.write("</hostnames>\n")
    out.write("<ports>")
    for state, counts in host.get("extraports", {}).items():
        out.write('<extraports state="%s" count="%d">\n' %
                  (state, counts["total"]))
        for reason, count in counts["reasons"].items():
            out.write('<extrareasons reason="%s" count="%d"/>\n' %
                      (reason, count))
        out.write("</extraports>\n")
    hostscripts: List[NmapScript] = []
    for p in host.get("ports", []):
        if p.get("port") == -1:
            hostscripts = p["scripts"]
            continue
        out.write("<port")
        if "protocol" in p:
            out.write(' protocol="%s"' % p["protocol"])
        if "port" in p:
            out.write(' portid="%s"' % p["port"])
        out.write("><state")
        for k in ["state", "reason", "reason_ttl"]:
            kk = "state_%s" % k
            if kk in p:
                out.write(" %s=%s" % (k, saxutils.quoteattr(str(p[kk]))))
        out.write("/>")
        if "service_name" in p:
            out.write('<service name="%s"' % p["service_name"])
            for k in [
                    "servicefp",
                    "product",
                    "version",
                    "extrainfo",
                    "ostype",
                    "method",
                    "conf",
            ]:
                kk = "service_%s" % k
                if kk in p:
                    if isinstance(p[kk], str):
                        out.write(" %s=%s" % (k, saxutils.quoteattr(p[kk])))
                    else:
                        out.write(' %s="%s"' % (k, p[kk]))
            # TODO: CPE
            out.write("></service>")
        for s in p.get("scripts", []):
            _display_xml_script(s, out=out)
        out.write("</port>\n")
    out.write("</ports>\n")
    if hostscripts:
        out.write("<hostscript>")
        for s in hostscripts:
            _display_xml_script(s, out=out)
        out.write("</hostscript>")
    for trace in host.get("traces", []):
        out.write("<trace")
        if "port" in trace:
            out.write(" port=%s" % (saxutils.quoteattr(str(trace["port"]))))
        if "protocol" in trace:
            out.write(" proto=%s" % (saxutils.quoteattr(trace["protocol"])))
        out.write(">\n")
        for hop in sorted(trace.get("hops", []),
                          key=lambda hop: cast(int, hop["ttl"])):
            out.write("<hop")
            if "ttl" in hop:
                out.write(" ttl=%s" % (saxutils.quoteattr(str(hop["ttl"]))))
            if "ipaddr" in hop:
                out.write(" ipaddr=%s" % (saxutils.quoteattr(hop["ipaddr"])))
            if "rtt" in hop:
                out.write(
                    " rtt=%s" %
                    (saxutils.quoteattr("%.2f" % hop["rtt"] if isinstance(
                        hop["rtt"], float) else hop["rtt"])))
            if "host" in hop:
                out.write(" host=%s" % (saxutils.quoteattr(hop["host"])))
            out.write("/>\n")
        out.write("</trace>\n")
    out.write("</host>\n")
Exemple #6
0
def main():
    if USING_ARGPARSE:
        parser = argparse.ArgumentParser(description=__doc__)
        parser.add_argument('ips_or_macs',
                            nargs='*',
                            help='Display results for specified IP (or '
                            'networks) or MAC addresses (or MAC address '
                            'regexps).')
    else:
        parser = optparse.OptionParser(description=__doc__)
        parser.parse_args_orig = parser.parse_args

        def my_parse_args():
            res = parser.parse_args_orig()
            res[0].ensure_value('ips_or_macs', res[1])
            return res[0]

        parser.parse_args = my_parse_args
        parser.add_argument = parser.add_option
    parser.add_argument('-s', '--sensor')
    parser.add_argument('-c', '--count', action="store_true")
    parser.add_argument('-r',
                        '--resolve',
                        action="store_true",
                        help="Resolve MAC manufacturer")
    args = parser.parse_args()
    flts = ([], [])  # MAC & IP filters
    for arg in args.ips_or_macs:
        if arg[:1] in "-!~":
            neg = True
            arg = arg[1:]
        else:
            neg = False
        match = MAC_ADDR.search(arg)
        if match:
            flts[0].append(db.passive.searchmac(mac=arg, neg=neg))
        elif arg.startswith('/') and '/' in arg[1:]:
            flts[0].append(
                db.passive.searchmac(mac=utils.str2regexp(arg), neg=neg))
        elif '/' in arg:
            flts[1].append(db.passive.searchnet(arg, neg=neg))
        else:
            flts[1].append(db.passive.searchhost(arg, neg=neg))
    if not flts[0]:
        flts[0].append(db.passive.searchmac())
    flt = db.passive.flt_or(*flts[0])
    if flts[1]:
        flt = db.passive.flt_and(flt, db.passive.flt_or(*flts[1]))
    if args.sensor is not None:
        flt = db.passive.flt_and(flt, args.sensor)
    if args.count:
        print(db.passive.count(flt))
        return
    for rec in db.passive.get(flt,
                              sort=[('addr', 1), ('value', 1), ('source', 1)]):
        rec["times"] = "s" if rec["count"] > 1 else ""
        if not rec.get("sensor"):
            rec["sensor"] = "-"
        if args.resolve:
            try:
                manuf = utils.mac2manuf(rec['value'])[0]
            except (TypeError, ValueError):
                pass
            else:
                rec['value'] = '%s (%s)' % (rec['value'], manuf)
        print("%(addr)s at %(value)s on %(sensor)s (%(source)s %(count)s "
              "time%(times)s, %(firstseen)s - %(lastseen)s)" % rec)
Exemple #7
0
def displayhost(record,
                showscripts=True,
                showtraceroute=True,
                showos=True,
                out=sys.stdout):
    """Displays (on `out`, by default `sys.stdout`) the Nmap scan
    result contained in `record`.

    """
    line = "Host %s" % utils.force_int2ip(record['addr'])
    if record.get('hostnames'):
        line += " (%s)" % '/'.join(x['name'] for x in record['hostnames'])
    if 'source' in record:
        line += ' from %s' % record['source']
    if record.get('categories'):
        line += ' (%s)' % ', '.join(record['categories'])
    if 'state' in record:
        line += ' (%s' % record['state']
        if 'state_reason' in record:
            line += ': %s' % record['state_reason']
        line += ')\n'
    out.write(line)
    if 'infos' in record:
        infos = record['infos']
        if 'country_code' in infos or 'country_name' in infos:
            out.write("\t%s - %s" % (infos.get(
                'country_code', '?'), infos.get('country_name', '?')))
            if 'city' in infos:
                out.write(' - %s' % infos['city'])
            out.write('\n')
        if 'as_num' in infos or 'as_name' in infos:
            out.write("\tAS%s - %s\n" %
                      (infos.get('as_num', '?'), infos.get('as_name', '?')))
    if 'starttime' in record and 'endtime' in record:
        out.write("\tscan %s - %s\n" %
                  (record['starttime'], record['endtime']))
    for state, counts in viewitems(record.get('extraports', {})):
        out.write("\t%d ports %s (%s)\n" % (counts["total"], state, ", ".join(
            "%d %s" % (count, reason)
            for reason, count in viewitems(counts["reasons"])
            if reason != "total")))
    ports = record.get('ports', [])
    ports.sort(
        key=lambda x: (utils.key_sort_none(x.get('protocol')), x['port']))
    for port in ports:
        if port.get('port') == -1:
            if 'scripts' in port:
                record['scripts'] = port['scripts']
            continue
        if 'state_reason' in port:
            reason = " (%s)" % ', '.join([port['state_reason']] + [
                "%s=%s" % (field[13:], value)
                for field, value in viewitems(port)
                if field.startswith('state_reason_')
            ])
        else:
            reason = ""
        if 'service_name' in port:
            srv = port['service_name']
            if 'service_method' in port:
                srv += ' (%s)' % port['service_method']
            for field in [
                    'service_product', 'service_version', 'service_extrainfo',
                    'service_ostype', 'service_hostname'
            ]:
                if field in port:
                    srv += ' %s' % port[field]
        else:
            srv = ""
        out.write("\t%-10s%-8s%-22s%s\n" %
                  ('%s/%d' % (port.get('protocol'), port['port']),
                   port.get('state_state', ''), reason, srv))
        if showscripts:
            out.writelines(_scriptoutput(port))
    if showscripts:
        scripts = _scriptoutput(record)
        if scripts:
            out.write('\tHost scripts:\n')
            out.writelines(scripts)
    mac_addrs = record.get('addresses', {}).get('mac')
    if mac_addrs:
        for addr in mac_addrs:
            out.write('\tMAC Address: %s' % addr)
            manuf = utils.mac2manuf(addr)
            if manuf and manuf[0]:
                out.write(' (%s)' % manuf[0])
            out.write('\n')
    if showtraceroute and record.get('traces'):
        for trace in record['traces']:
            proto = trace['protocol']
            if proto in ['tcp', 'udp']:
                proto += '/%d' % trace['port']
            out.write('\tTraceroute (using %s)\n' % proto)
            hops = trace['hops']
            hops.sort(key=lambda hop: hop['ttl'])
            for hop in hops:
                out.write('\t\t%3s %15s %7s\n' % (
                    hop['ttl'],
                    utils.force_int2ip(hop['ipaddr']),
                    hop['rtt'],
                ))
    if showos and record.get('os', {}).get('osclass'):
        osclasses = record['os']['osclass']
        maxacc = str(max(int(x['accuracy']) for x in osclasses))
        osclasses = [
            osclass for osclass in osclasses if osclass['accuracy'] == maxacc
        ]
        out.write('\tOS fingerprint\n')
        for osclass in osclasses:
            out.write('\t\t%(osfamily)s / %(type)s / %(vendor)s / '
                      'accuracy = %(accuracy)s\n' % osclass)
Exemple #8
0
def displayhost(record,
                showscripts=True,
                showtraceroute=True,
                showos=True,
                out=sys.stdout):
    """Displays (on `out`, by default `sys.stdout`) the Nmap scan
    result contained in `record`.

    """
    line = "Host %s" % utils.force_int2ip(record["addr"])
    if record.get("hostnames"):
        line += " (%s)" % "/".join(x["name"] for x in record["hostnames"])
    if "source" in record:
        line += " from %s" % ("/".join(record["source"]) if isinstance(
            record["source"], list) else record["source"])
    if record.get("categories"):
        line += " (%s)" % ", ".join(
            cat for cat in record["categories"] if not cat.startswith("_"))
    if "state" in record:
        line += " (%s" % record["state"]
        if "state_reason" in record:
            line += ": %s" % record["state_reason"]
        line += ")\n"
    out.write(line)
    if "infos" in record:
        infos = record["infos"]
        if "country_code" in infos or "country_name" in infos:
            out.write("\t%s - %s" % (infos.get(
                "country_code", "?"), infos.get("country_name", "?")))
            if "city" in infos:
                out.write(" - %s" % infos["city"])
            out.write("\n")
        if "as_num" in infos or "as_name" in infos:
            out.write("\tAS%s - %s\n" %
                      (infos.get("as_num", "?"), infos.get("as_name", "?")))
    if "starttime" in record and "endtime" in record:
        out.write("\tscan %s - %s\n" %
                  (record["starttime"], record["endtime"]))
    for state, counts in record.get("extraports", {}).items():
        out.write("\t%d ports %s (%s)\n" % (
            counts["total"],
            state,
            ", ".join("%d %s" % (count, reason)
                      for reason, count in counts["reasons"].items()
                      if reason != "total"),
        ))
    ports = record.get("ports", [])
    ports.sort(
        key=lambda x: (utils.key_sort_none(x.get("protocol")), x["port"]))
    for port in ports:
        if port.get("port") == -1:
            if "scripts" in port:
                record["scripts"] = port["scripts"]
            continue
        if "state_reason" in port:
            reason = " (%s)" % ", ".join([port["state_reason"]] + [
                "%s=%s" % (field[13:], value) for field, value in port.items()
                if field.startswith("state_reason_")
            ])
        else:
            reason = ""
        srv = []
        if "service_name" in port:
            srv.append("")
            if "service_tunnel" in port:
                srv.append("%s/%s" %
                           (port["service_name"], port["service_tunnel"]))
            else:
                srv.append(port["service_name"])
            if "service_method" in port:
                srv.append("(%s)" % port["service_method"])
            for field in [
                    "service_product",
                    "service_version",
                    "service_extrainfo",
                    "service_ostype",
                    "service_hostname",
            ]:
                if field in port:
                    srv.append(port[field])
        out.write("\t%-10s%-8s%-22s%s\n" % (
            "%s/%d" % (port.get("protocol"), port["port"]),
            port.get("state_state", ""),
            reason,
            " ".join(srv),
        ))
        if showscripts:
            out.writelines(_scriptoutput(port))
    if showscripts:
        scripts = _scriptoutput(record)
        if scripts:
            out.write("\tHost scripts:\n")
            out.writelines(scripts)
    mac_addrs = record.get("addresses", {}).get("mac")
    if mac_addrs:
        for addr in mac_addrs:
            out.write("\tMAC Address: %s" % addr)
            manuf = utils.mac2manuf(addr)
            if manuf and manuf[0]:
                out.write(" (%s)" % manuf[0])
            out.write("\n")
    if showtraceroute and record.get("traces"):
        for trace in record["traces"]:
            proto = trace["protocol"]
            if proto in ["tcp", "udp"]:
                proto += "/%d" % trace["port"]
            out.write("\tTraceroute (using %s)\n" % proto)
            hops = trace["hops"]
            hops.sort(key=lambda hop: hop["ttl"])
            for hop in hops:
                out.write("\t\t%3s %15s %7s\n" % (
                    hop["ttl"],
                    utils.force_int2ip(hop["ipaddr"]),
                    hop["rtt"],
                ))
    if showos and record.get("os", {}).get("osclass"):
        osclasses = record["os"]["osclass"]
        maxacc = str(max(int(x["accuracy"]) for x in osclasses))
        osclasses = [
            osclass for osclass in osclasses if osclass["accuracy"] == maxacc
        ]
        out.write("\tOS fingerprint\n")
        for osclass in osclasses:
            out.write("\t\t%(osfamily)s / %(type)s / %(vendor)s / "
                      "accuracy = %(accuracy)s\n" % osclass)