#
# This script was written by Michel Arboi <arboi@alussinan.org>
#
# GPL
#

if(description)
{
 script_id(14274);
 script_version ("1.5");
 script_tag(name:"risk_factor", value:"None");
 name = "snmpwalk 'scanner'";
 script_name(name);
 
 desc = "
This plugin runs snmpwalk against the remote machine to find open ports.
See the section 'plugins options' to configure it

Risk factor : None";

 script_description(desc);
 
 summary = "Find open ports with snmpwalk";
 script_summary(summary);
 
 script_category(ACT_SCANNER);
 
 script_copyright("This script is Copyright (C) 2004 Michel Arboi");
 family = "Port scanners";
 script_family(family);

 script_dependencies("ping_host.nasl");

 script_add_preference(name: "Community name :", type: "entry", value: "public");
 script_add_preference(name: "SNMP protocol :", type: "radio", value: "1;2c");
 script_add_preference(name: "SNMP transport layer :", type: "radio", value: "udp;tcp");
 script_add_preference(name: "TCP/UDP port :", type: "entry", value: "");
 script_add_preference(name: "Number of retries :", type: "entry", value: "");
 script_add_preference(name: "Timeout between retries :", type: "entry", value: "");
 if(defined_func("script_mandatory_keys"))
  script_mandatory_keys("Tools/Present/snmpwalk");
 exit(0);
}

# script_mandatory_keys compatibility:
include ("toolcheck.inc");
exit_if_not_found (toolname: "snmpwalk");
# end of script_mandatory_keys compatibility

#

check = 
 (! safe_checks()) ||
 ("yes" >< get_kb_item("global_settings/experimental_scripts_tests")) ||
 ("yes" >< get_preference("unscanned_closed")) ||
 ("yes" >< get_kb_item("global_settings/thorough_tests"));
# ("Avoid false alarms" >< get_kb_item("global_settings/report_paranoia"))

global_var	snmp_layer, argv, snmp_port, snmp_comm;
seen_tcp_ports = make_list(0);	# Do not want to see this!
seen_udp_ports = make_list(0);	# Do not want to see this!

function make_argv(obj)
{
 local_var	i, p;

 i = 0;
 argv = NULL;
 argv[i++] = "snmpwalk";

 p = script_get_preference("SNMP protocol :");
 if (! p) p = "2c";
 argv[i++] = "-v";
 argv[i++] = p;

 snmp_layer = "udp";

 if (! v506)
 {
  p = script_get_preference("SNMP transport layer :");
  if (p)
  {
   argv[i++] = "-T";
   argv[i++] = p;
   snmp_layer = p;
  }
 }

 p = script_get_preference("Number of retries :");
 if (p && p =~ '^[0-9]+$')
 {
  argv[i++] = "-r";
  argv[i++] = p;
 }

 p = script_get_preference("Timeout between retries :");
 if (p && p =~ '^[0-9]+$')
 {
  argv[i++] = "-t";
  argv[i++] = p;
 }

 p = script_get_preference("TCP/UDP port :");
 if (p && p =~ '^[0-9]+$')
 {
  argv[i++] = "-p";
  argv[i++] = p;
  snmp_port = p;
 }

 if (!v506) argv[i++] = ip;

 p = script_get_preference("Community name :");
 if (strlen(p) == 0) p = "public";
 if (v506) argv[i++] = "-c";
 argv[i++] = p;
 snmp_comm = p;

 # Version 5.0.6 orlater: put the hostname *after* the options
 if (v506) argv[i++] = ip;

 argv[i++] = obj;
}


ver = pread(cmd: "snmpwalk", argv: make_list("snmpwalk", "-V"));
if (ereg(string: ver, pattern: "NET-SNMP version: +([6-9]\.|5\.([1-9]|0\.[6-9]))", icase: 1, multiline: 1))
  v506 = 1;
else
  v506 = 0;

ip = get_host_ip();

i = 0;
scanned = 0; udp_scanned = 0;
foreach o (
  make_list("tcp.tcpConnTable.tcpConnEntry.tcpConnLocalPort.0.0.0.0",
            "tcp.tcpConnTable.tcpConnEntry.tcpConnLocalPort." + ip,
            "udp.udpTable.udpEntry.udpLocalPort.0.0.0.0", 
            "udp.udpTable.udpEntry.udpLocalPort." + ip))
{
 scanner_status(current: 0, total: i++);
 make_argv(obj: o);
 buf = pread(cmd: "snmpwalk", argv: argv);
 proto = substr(o, 0, 2);
 if (buf)
 {
  foreach line( split(buf))
  {
   v = eregmatch(pattern: '=[ \t]*([a-zA-Z0-9-]+:)?[ \t]*([0-9]+)[ \t\r\n]*$',
		string: line);
   if (! isnull(v))
   {
    port = v[2];
    if (proto == 'tcp' && ! seen_tcp_ports[port])
    {
     if (check && proto == "tcp")
     {
      soc = open_sock_tcp(port);
      if (soc)
      {
       scanner_add_port(proto: proto, port: port);
       close(soc);
      }
      else
       display("snmpwalk_portscan(", get_host_ip(), "): TCP port ",  port, " is closed in fact\n");
     }
     else
      scanner_add_port(proto: proto, port: port);
     seen_tcp_ports[port] ++;
    scanned ++;
    }
    if (proto == "udp" && ! seen_udp_ports[port])
    {
     scanner_add_port(proto: proto, port: port);
     seen_udp_ports[port] ++;
     udp_scanned ++;
    }
   }
  }
 } 
}

if (scanned)
{
 set_kb_item(name: "Host/scanned", value: TRUE);
 set_kb_item(name: "Host/full_scan", value: TRUE);
 set_kb_item(name: 'Host/scanners/snmpwalk', value: TRUE);
 security_note(port: snmp_port, proto: snmp_layer, 
data: strcat("snmpwalk could get the open port list with the community name ", snmp_comm));
}

if (udp_scanned) set_kb_item(name: "Host/udp_scanned", value: TRUE);

exit(0);

# make_argv(obj: "host.hrSWInstalled.hrSWInstalledTable.hrSWInstalledEntry.hrSWInstalledName");

