mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 05:01:29 +00:00
Make osclasses a substructure of osmatch.
This commit is contained in:
@@ -1851,29 +1851,19 @@ class NetNode(Node):
|
|||||||
if host.uptime.get("seconds") or host.uptime.get("lastboot"):
|
if host.uptime.get("seconds") or host.uptime.get("lastboot"):
|
||||||
return host.uptime
|
return host.uptime
|
||||||
elif info == "device_type":
|
elif info == "device_type":
|
||||||
if len(host.osclasses) == 0:
|
osmatch = host.get_best_osmatch()
|
||||||
|
if osmatch is None:
|
||||||
|
return None
|
||||||
|
osclasses = osmatch['osclasses']
|
||||||
|
if len(osclasses) == 0:
|
||||||
return None
|
return None
|
||||||
types = ["router", "wap", "switch", "firewall"]
|
types = ["router", "wap", "switch", "firewall"]
|
||||||
for type in types:
|
for type in types:
|
||||||
if type in host.osclasses[0].get("type", "").lower():
|
if type in osclasses[0].get("type", "").lower():
|
||||||
return type
|
return type
|
||||||
elif info == "os":
|
elif info == "os":
|
||||||
os = {}
|
os = {}
|
||||||
|
|
||||||
os_classes = []
|
|
||||||
for osclass in host.osclasses:
|
|
||||||
os_class = {}
|
|
||||||
|
|
||||||
os_class["type"] = osclass.get("type", "")
|
|
||||||
os_class["vendor"] = osclass.get("vendor", "")
|
|
||||||
#os_class["accuracy"] = int(osclass.get("accuracy", ""))
|
|
||||||
os_class["accuracy"] = osclass.get("accuracy", "")
|
|
||||||
os_class["os_family"] = osclass.get("osfamily", "")
|
|
||||||
os_class["os_gen"] = osclass.get("osgen", "")
|
|
||||||
|
|
||||||
os_classes.append(os_class)
|
|
||||||
os["classes"] = os_classes
|
|
||||||
|
|
||||||
# osmatches
|
# osmatches
|
||||||
if len(host.osmatches) > 0 and \
|
if len(host.osmatches) > 0 and \
|
||||||
host.osmatches[0]["accuracy"] != "" and \
|
host.osmatches[0]["accuracy"] != "" and \
|
||||||
@@ -1883,6 +1873,20 @@ class NetNode(Node):
|
|||||||
os["matches"] = host.osmatches
|
os["matches"] = host.osmatches
|
||||||
os["matches"][0]["db_line"] = 0 # not supported
|
os["matches"][0]["db_line"] = 0 # not supported
|
||||||
|
|
||||||
|
os_classes = []
|
||||||
|
for osclass in host.osmatches[0]["osclasses"]:
|
||||||
|
os_class = {}
|
||||||
|
|
||||||
|
os_class["type"] = osclass.get("type", "")
|
||||||
|
os_class["vendor"] = osclass.get("vendor", "")
|
||||||
|
#os_class["accuracy"] = int(osclass.get("accuracy", ""))
|
||||||
|
os_class["accuracy"] = osclass.get("accuracy", "")
|
||||||
|
os_class["os_family"] = osclass.get("osfamily", "")
|
||||||
|
os_class["os_gen"] = osclass.get("osgen", "")
|
||||||
|
|
||||||
|
os_classes.append(os_class)
|
||||||
|
os["classes"] = os_classes
|
||||||
|
|
||||||
# ports_used
|
# ports_used
|
||||||
if len(host.ports_used) > 0:
|
if len(host.ports_used) > 0:
|
||||||
if os == None:
|
if os == None:
|
||||||
|
|||||||
@@ -125,12 +125,21 @@ class TracerouteHostInfo(object):
|
|||||||
self.hostname = None
|
self.hostname = None
|
||||||
self.ports = []
|
self.ports = []
|
||||||
self.extraports = []
|
self.extraports = []
|
||||||
self.osclasses = []
|
|
||||||
self.osmatches = []
|
self.osmatches = []
|
||||||
|
|
||||||
def get_hostname(self):
|
def get_hostname(self):
|
||||||
return self.hostname
|
return self.hostname
|
||||||
|
|
||||||
|
def get_best_osmatch(self):
|
||||||
|
if not self.osmatches:
|
||||||
|
return None
|
||||||
|
def osmatch_key(osmatch):
|
||||||
|
try:
|
||||||
|
return -float(osmatch["accuracy"])
|
||||||
|
except ValueError:
|
||||||
|
return 0
|
||||||
|
return sorted(self.osmatches, key = osmatch_key)[0]
|
||||||
|
|
||||||
hostnames = property(lambda self: self.hostname and [self.hostname] or [])
|
hostnames = property(lambda self: self.hostname and [self.hostname] or [])
|
||||||
|
|
||||||
def make_graph_from_hosts(hosts):
|
def make_graph_from_hosts(hosts):
|
||||||
|
|||||||
@@ -257,8 +257,7 @@ class NetworkInventory(object):
|
|||||||
# OS detection fields
|
# OS detection fields
|
||||||
# Replace old_host's OS detection fields with new_host's if old_host has no
|
# Replace old_host's OS detection fields with new_host's if old_host has no
|
||||||
# OS detection info or new_host's info is newer.
|
# OS detection info or new_host's info is newer.
|
||||||
if len(new_host.osclasses) > 0 and (len(old_host.osclasses) == 0 or old_date < new_date):
|
if len(new_host.osmatches) > 0 and (len(old_host.osmatches) == 0 or old_date < new_date):
|
||||||
old_host.osclasses = new_host.osclasses
|
|
||||||
old_host.osmatches = new_host.osmatches
|
old_host.osmatches = new_host.osmatches
|
||||||
old_host.ports_used = new_host.ports_used
|
old_host.ports_used = new_host.ports_used
|
||||||
|
|
||||||
@@ -633,7 +632,6 @@ if __name__ == "__main__":
|
|||||||
#for port in host.ports:
|
#for port in host.ports:
|
||||||
# print " %s: %s" % (port["portid"], port["port_state"])
|
# print " %s: %s" % (port["portid"], port["port_state"])
|
||||||
#print " OS matches: %s" % host.osmatches
|
#print " OS matches: %s" % host.osmatches
|
||||||
#print " OS classes: %s" % host.osclasses
|
|
||||||
#print " Ports used: %s" % host.ports_used
|
#print " Ports used: %s" % host.ports_used
|
||||||
#print " Trace: %s" % host.trace
|
#print " Trace: %s" % host.trace
|
||||||
#if "hops" in host.trace:
|
#if "hops" in host.trace:
|
||||||
|
|||||||
@@ -111,13 +111,12 @@ from zenmapCore.NmapOptions import NmapOptions, split_quoted, join_quoted
|
|||||||
from zenmapCore.StringPool import unique
|
from zenmapCore.StringPool import unique
|
||||||
|
|
||||||
# The version of the Nmap DTD this file understands and emits.
|
# The version of the Nmap DTD this file understands and emits.
|
||||||
XML_OUTPUT_VERSION = "1.03"
|
XML_OUTPUT_VERSION = "1.04"
|
||||||
|
|
||||||
class HostInfo(object):
|
class HostInfo(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.comment = None;
|
self.comment = None;
|
||||||
self._tcpsequence = {}
|
self._tcpsequence = {}
|
||||||
self._osclasses = []
|
|
||||||
self._osmatches = []
|
self._osmatches = []
|
||||||
self._ports = []
|
self._ports = []
|
||||||
self._ports_used = []
|
self._ports_used = []
|
||||||
@@ -137,8 +136,7 @@ class HostInfo(object):
|
|||||||
clone = HostInfo()
|
clone = HostInfo()
|
||||||
clone.comment = self.comment
|
clone.comment = self.comment
|
||||||
clone._tcpsequence = copy.deepcopy(self._tcpsequence)
|
clone._tcpsequence = copy.deepcopy(self._tcpsequence)
|
||||||
clone._osclasses = map(lambda d: copy.deepcopy(d), self._osclasses)
|
clone._osmatches = copy.deepcopy(self._osmatches)
|
||||||
clone._osmatches = self._osmatches
|
|
||||||
clone._ports = copy.deepcopy(self._ports)
|
clone._ports = copy.deepcopy(self._ports)
|
||||||
clone._ports_used = self._ports_used
|
clone._ports_used = self._ports_used
|
||||||
clone._extraports = self._extraports
|
clone._extraports = self._extraports
|
||||||
@@ -188,17 +186,12 @@ class HostInfo(object):
|
|||||||
return self._ipidsequence
|
return self._ipidsequence
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# osclasses is a list containing dicts of the form
|
# osmatches is a list of dicts of the form
|
||||||
|
# {'name': u'Linux 2.6.24', 'accuracy': u'98', 'line': u'1000',
|
||||||
|
# 'osclasses': ...}
|
||||||
|
# where each 'osclasses' element is a dict of the form
|
||||||
# {'vendor': u'Linux', 'osfamily': u'Linux', 'type': u'general purpose',
|
# {'vendor': u'Linux', 'osfamily': u'Linux', 'type': u'general purpose',
|
||||||
# 'osgen': u'2.6.X', 'accuracy': u'98'}
|
# 'osgen': u'2.6.X', 'accuracy': u'98'}
|
||||||
def set_osclasses(self, classes):
|
|
||||||
self._osclasses = classes
|
|
||||||
|
|
||||||
def get_osclasses(self):
|
|
||||||
return self._osclasses
|
|
||||||
|
|
||||||
# osmatches is a list of dicts of the form
|
|
||||||
# {'name': u'Linux 2.6.24', 'accuracy': u'98', 'line': u'1000'}
|
|
||||||
def set_osmatches(self, matches):
|
def set_osmatches(self, matches):
|
||||||
self._osmatches = matches
|
self._osmatches = matches
|
||||||
|
|
||||||
@@ -222,22 +215,6 @@ class HostInfo(object):
|
|||||||
return osmatches[-1]
|
return osmatches[-1]
|
||||||
|
|
||||||
|
|
||||||
def get_best_osclass(self):
|
|
||||||
"""Return the OS class with the highest accuracy. If there is a tie, one
|
|
||||||
of the best matches will be returned."""
|
|
||||||
if not self._osclasses:
|
|
||||||
return None
|
|
||||||
def osclass_key(osclass):
|
|
||||||
# Sort first by accuracy, then by name so it's deterministic.
|
|
||||||
try:
|
|
||||||
accuracy = float(osclass.get("accuracy", ""))
|
|
||||||
except ValueError:
|
|
||||||
accuracy = 0
|
|
||||||
return (accuracy, osclass.get("name"))
|
|
||||||
osclasses = self.osclasses[:]
|
|
||||||
osclasses.sort(cmp = lambda a, b: cmp(osclass_key(a), osclass_key(b)))
|
|
||||||
return osclasses[-1]
|
|
||||||
|
|
||||||
# ports_used is a list like
|
# ports_used is a list like
|
||||||
# [{'state': u'open', 'portid': u'22', 'proto': u'tcp'},
|
# [{'state': u'open', 'portid': u'22', 'proto': u'tcp'},
|
||||||
# {'state': u'closed', 'portid': u'25', 'proto': u'tcp'},
|
# {'state': u'closed', 'portid': u'25', 'proto': u'tcp'},
|
||||||
@@ -429,7 +406,6 @@ class HostInfo(object):
|
|||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
tcpsequence = property(get_tcpsequence, set_tcpsequence)
|
tcpsequence = property(get_tcpsequence, set_tcpsequence)
|
||||||
osclasses = property(get_osclasses, set_osclasses)
|
|
||||||
osmatches = property(get_osmatches, set_osmatches)
|
osmatches = property(get_osmatches, set_osmatches)
|
||||||
ports = property(get_ports, set_ports)
|
ports = property(get_ports, set_ports)
|
||||||
ports_used = property(get_ports_used, set_ports_used)
|
ports_used = property(get_ports_used, set_ports_used)
|
||||||
@@ -876,7 +852,9 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
|||||||
self.dic_port["service_extrainfo"] = attrs.get("extrainfo", "")
|
self.dic_port["service_extrainfo"] = attrs.get("extrainfo", "")
|
||||||
|
|
||||||
def _parse_host_osmatch(self, attrs):
|
def _parse_host_osmatch(self, attrs):
|
||||||
self.list_osmatch.append(self._parsing(attrs, [], ['name', 'accuracy', 'line']))
|
osmatch = self._parsing(attrs, [], ['name', 'accuracy', 'line'])
|
||||||
|
osmatch['osclasses'] = []
|
||||||
|
self.list_osmatch.append(osmatch)
|
||||||
|
|
||||||
def _parse_host_portused(self, attrs):
|
def _parse_host_portused(self, attrs):
|
||||||
self.list_portused.append(self._parsing(attrs, ['state', 'proto', 'portid'], []))
|
self.list_portused.append(self._parsing(attrs, ['state', 'proto', 'portid'], []))
|
||||||
@@ -972,12 +950,12 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
|||||||
self.in_os = True
|
self.in_os = True
|
||||||
self.list_portused = []
|
self.list_portused = []
|
||||||
self.list_osmatch = []
|
self.list_osmatch = []
|
||||||
self.list_osclass = []
|
|
||||||
elif self.in_host and self.in_os and name == "osmatch":
|
elif self.in_host and self.in_os and name == "osmatch":
|
||||||
self._parse_host_osmatch(attrs)
|
self._parse_host_osmatch(attrs)
|
||||||
elif self.in_host and self.in_os and name == "portused":
|
elif self.in_host and self.in_os and name == "portused":
|
||||||
self._parse_host_portused(attrs)
|
self._parse_host_portused(attrs)
|
||||||
elif self.in_host and self.in_os and name == "osclass":
|
elif self.in_host and self.in_os and name == "osclass":
|
||||||
|
self.list_osclass = []
|
||||||
self._parse_host_osclass(attrs)
|
self._parse_host_osclass(attrs)
|
||||||
elif self.in_host and name == "uptime":
|
elif self.in_host and name == "uptime":
|
||||||
self._parse_host_uptime(attrs)
|
self._parse_host_uptime(attrs)
|
||||||
@@ -1015,15 +993,16 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
|||||||
self.in_port = False
|
self.in_port = False
|
||||||
self.list_ports.append(self.dic_port)
|
self.list_ports.append(self.dic_port)
|
||||||
del(self.dic_port)
|
del(self.dic_port)
|
||||||
|
elif self.in_host and self.in_os and name == "osmatch":
|
||||||
|
self.list_osmatch[-1]['osclasses'].extend(self.list_osclass)
|
||||||
|
self.list_osclass = []
|
||||||
elif self.in_host and self.in_os and name == "os":
|
elif self.in_host and self.in_os and name == "os":
|
||||||
self.in_os = False
|
self.in_os = False
|
||||||
self.host_info.set_ports_used(self.list_portused)
|
self.host_info.set_ports_used(self.list_portused)
|
||||||
self.host_info.set_osmatches(self.list_osmatch)
|
self.host_info.set_osmatches(self.list_osmatch)
|
||||||
self.host_info.set_osclasses(self.list_osclass)
|
|
||||||
|
|
||||||
del(self.list_portused)
|
del(self.list_portused)
|
||||||
del(self.list_osmatch)
|
del(self.list_osmatch)
|
||||||
del(self.list_osclass)
|
|
||||||
elif self.in_host and self.in_trace and name == "trace":
|
elif self.in_host and self.in_trace and name == "trace":
|
||||||
self.in_trace = False
|
self.in_trace = False
|
||||||
|
|
||||||
@@ -1213,22 +1192,21 @@ class NmapParserSAX(ParserBasics, ContentHandler):
|
|||||||
portid = pu.get("portid", ""))))
|
portid = pu.get("portid", ""))))
|
||||||
writer.endElement("portused")
|
writer.endElement("portused")
|
||||||
|
|
||||||
## Osclass elements
|
|
||||||
for oc in host.osclasses:
|
|
||||||
writer.startElement("osclass",
|
|
||||||
Attributes(dict(vendor = oc.get("vendor", ""),
|
|
||||||
osfamily = oc.get("osfamily", ""),
|
|
||||||
type = oc.get("type", ""),
|
|
||||||
osgen = oc.get("osgen", ""),
|
|
||||||
accuracy = oc.get("accuracy", ""))))
|
|
||||||
writer.endElement("osclass")
|
|
||||||
|
|
||||||
## Osmatch elements
|
## Osmatch elements
|
||||||
for om in host.osmatches:
|
for om in host.osmatches:
|
||||||
writer.startElement("osmatch",
|
writer.startElement("osmatch",
|
||||||
Attributes(dict(name = om.get("name", ""),
|
Attributes(dict(name = om.get("name", ""),
|
||||||
accuracy = om.get("accuracy", ""),
|
accuracy = om.get("accuracy", ""),
|
||||||
line = om.get("line", ""))))
|
line = om.get("line", ""))))
|
||||||
|
## Osclass elements
|
||||||
|
for oc in om['osclasses']:
|
||||||
|
writer.startElement("osclass",
|
||||||
|
Attributes(dict(vendor = oc.get("vendor", ""),
|
||||||
|
osfamily = oc.get("osfamily", ""),
|
||||||
|
type = oc.get("type", ""),
|
||||||
|
osgen = oc.get("osgen", ""),
|
||||||
|
accuracy = oc.get("accuracy", ""))))
|
||||||
|
writer.endElement("osclass")
|
||||||
writer.endElement("osmatch")
|
writer.endElement("osmatch")
|
||||||
|
|
||||||
writer.endElement("os")
|
writer.endElement("os")
|
||||||
@@ -1358,7 +1336,7 @@ if __name__ == '__main__':
|
|||||||
for p in host.ports:
|
for p in host.ports:
|
||||||
print "\t%s" % repr(p)
|
print "\t%s" % repr(p)
|
||||||
print " Ports used:", repr(host.ports_used)
|
print " Ports used:", repr(host.ports_used)
|
||||||
print " OS Class:", repr(host.osclasses)
|
print " OS Matches:", repr(host.osmatches)
|
||||||
print " Hostnames:", repr(host.hostnames)
|
print " Hostnames:", repr(host.hostnames)
|
||||||
print " IP:", repr(host.ip)
|
print " IP:", repr(host.ip)
|
||||||
print " IPv6:", repr(host.ipv6)
|
print " IPv6:", repr(host.ipv6)
|
||||||
|
|||||||
@@ -148,15 +148,14 @@ class HostSearch(object):
|
|||||||
os = os.lower()
|
os = os.lower()
|
||||||
os_str = ""
|
os_str = ""
|
||||||
|
|
||||||
osclasses = host.get_osclasses()
|
|
||||||
osmatches = host.get_osmatches()
|
osmatches = host.get_osmatches()
|
||||||
|
|
||||||
for osclass in osclasses:
|
|
||||||
os_str += osclass['vendor'].lower() + " " +\
|
|
||||||
osclass['osfamily'].lower() + " " +\
|
|
||||||
osclass['type'].lower()
|
|
||||||
for osmatch in osmatches:
|
for osmatch in osmatches:
|
||||||
os_str += osmatch['name'].lower()
|
os_str += osmatch['name'].lower()
|
||||||
|
for osclass in osmatch['osmatches']:
|
||||||
|
os_str += osclass['vendor'].lower() + " " +\
|
||||||
|
osclass['osfamily'].lower() + " " +\
|
||||||
|
osclass['type'].lower()
|
||||||
|
|
||||||
if os in os_str:
|
if os in os_str:
|
||||||
return True
|
return True
|
||||||
@@ -566,7 +565,6 @@ if __name__ == "__main__":
|
|||||||
#port_filtered="",
|
#port_filtered="",
|
||||||
#port_closed="",
|
#port_closed="",
|
||||||
#service="",
|
#service="",
|
||||||
#osclass="Microsoft | Windows | 95/98/ME | General Purpose",
|
|
||||||
#osmatch="gentoo",
|
#osmatch="gentoo",
|
||||||
#product="Apache"\
|
#product="Apache"\
|
||||||
# ):
|
# ):
|
||||||
|
|||||||
@@ -148,8 +148,11 @@ if pixmap_path:
|
|||||||
iconfactory.add_default()
|
iconfactory.add_default()
|
||||||
|
|
||||||
def get_os_icon(host):
|
def get_os_icon(host):
|
||||||
osclass = host.get_best_osclass()
|
|
||||||
osmatch = host.get_best_osmatch()
|
osmatch = host.get_best_osmatch()
|
||||||
|
if osmatch and osmatch['osclasses']:
|
||||||
|
osclass = osmatch['osclasses'][0]
|
||||||
|
else:
|
||||||
|
osclass = None
|
||||||
|
|
||||||
if osclass and osmatch:
|
if osclass and osmatch:
|
||||||
return get_os(osclass['osfamily'], osmatch['name'], 'icon')
|
return get_os(osclass['osfamily'], osmatch['name'], 'icon')
|
||||||
@@ -157,8 +160,11 @@ def get_os_icon(host):
|
|||||||
return get_os(None, None, 'icon')
|
return get_os(None, None, 'icon')
|
||||||
|
|
||||||
def get_os_logo(host):
|
def get_os_logo(host):
|
||||||
osclass = host.get_best_osclass()
|
|
||||||
osmatch = host.get_best_osmatch()
|
osmatch = host.get_best_osmatch()
|
||||||
|
if osmatch and osmatch['osclasses']:
|
||||||
|
osclass = osmatch['osclasses'][0]
|
||||||
|
else:
|
||||||
|
osclass = None
|
||||||
|
|
||||||
if osclass and osmatch:
|
if osclass and osmatch:
|
||||||
return get_os(osclass['osfamily'], osmatch['name'], 'logo')
|
return get_os(osclass['osfamily'], osmatch['name'], 'logo')
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class HostDetails(HIGVBox):
|
|||||||
os = host.get_best_osmatch()
|
os = host.get_best_osmatch()
|
||||||
if os:
|
if os:
|
||||||
os['portsused'] = host.get_ports_used()
|
os['portsused'] = host.get_ports_used()
|
||||||
os['osclass'] = host.get_osclasses()
|
|
||||||
|
|
||||||
self.set_os(os)
|
self.set_os(os)
|
||||||
self.set_tcpseq(host.get_tcpsequence())
|
self.set_tcpseq(host.get_tcpsequence())
|
||||||
@@ -154,7 +153,7 @@ class HostDetails(HIGVBox):
|
|||||||
self.hostnames_expander = gtk.Expander('<b>'+_('Hostnames')+'</b>')
|
self.hostnames_expander = gtk.Expander('<b>'+_('Hostnames')+'</b>')
|
||||||
self.os_expander = gtk.Expander('<b>'+_('Operating System')+'</b>')
|
self.os_expander = gtk.Expander('<b>'+_('Operating System')+'</b>')
|
||||||
self.portsused_expander = gtk.Expander('<b>'+_('Ports used')+'</b>')
|
self.portsused_expander = gtk.Expander('<b>'+_('Ports used')+'</b>')
|
||||||
self.osclass_expander = gtk.Expander('<b>'+_('OS Class')+'</b>')
|
self.osclass_expander = gtk.Expander('<b>'+_('OS Classes')+'</b>')
|
||||||
self.tcp_expander = gtk.Expander('<b>'+_('TCP Sequence')+'</b>')
|
self.tcp_expander = gtk.Expander('<b>'+_('TCP Sequence')+'</b>')
|
||||||
self.ip_expander = gtk.Expander('<b>'+_('IP ID Sequence')+'</b>')
|
self.ip_expander = gtk.Expander('<b>'+_('IP ID Sequence')+'</b>')
|
||||||
self.tcpts_expander = gtk.Expander('<b>'+_('TCP TS Sequence')+'</b>')
|
self.tcpts_expander = gtk.Expander('<b>'+_('TCP TS Sequence')+'</b>')
|
||||||
@@ -368,7 +367,7 @@ class HostDetails(HIGVBox):
|
|||||||
except:pass
|
except:pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.set_osclass(os['osclass'])
|
self.set_osclass(os['osclasses'])
|
||||||
self.osclass_expander.set_use_markup(True)
|
self.osclass_expander.set_use_markup(True)
|
||||||
table.attach(self.osclass_expander,0,2,y1,y2)
|
table.attach(self.osclass_expander,0,2,y1,y2)
|
||||||
except:pass
|
except:pass
|
||||||
|
|||||||
Reference in New Issue
Block a user