Index: service_scan.cc =================================================================== --- service_scan.cc (.../nmap) (revision 13362) +++ service_scan.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -98,6 +98,7 @@ #include "nsock.h" #include "Target.h" #include "utils.h" +#include "protocols.h" #include "nmap_tty.h" @@ -1244,6 +1245,9 @@ } else if (proto == IPPROTO_UDP) { p = excludedports.udp_ports; count = excludedports.udp_count; + } else if (proto == IPPROTO_SCTP) { + p = excludedports.sctp_ports; + count = excludedports.sctp_count; } else { fatal("Bad proto number (%d) specified in %s", proto, __func__); } @@ -1630,7 +1634,7 @@ num_hosts_timedout++; continue; } - while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDP, PORT_OPEN))) { + while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDPANDSCTP, PORT_OPEN))) { svc = new ServiceNFO(AP); svc->target = Targets[targetno]; svc->portno = nxtport->portno; @@ -1648,7 +1652,7 @@ if (Targets[targetno]->timedOut(&now)) { continue; } - while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDP, PORT_OPENFILTERED))) { + while((nxtport = Targets[targetno]->ports.nextPort(nxtport, TCPANDUDPANDSCTP, PORT_OPENFILTERED))) { svc = new ServiceNFO(AP); svc->target = Targets[targetno]; svc->portno = nxtport->portno; @@ -2350,7 +2354,8 @@ svc = *i; if (AP->isExcluded(svc->portno, svc->proto)) { - if (o.debugging) log_write(LOG_PLAIN, "EXCLUDING %d/%s\n", svc->portno, svc->proto==IPPROTO_TCP ? "tcp" : "udp"); + if (o.debugging) log_write(LOG_PLAIN, "EXCLUDING %d/%s\n", svc->portno, + IPPROTO2STR(svc->proto)); svc->port->setServiceProbeResults(PROBESTATE_EXCLUDED, NULL, SERVICE_TUNNEL_NONE, Index: global_structures.h =================================================================== --- global_structures.h (.../nmap) (revision 13362) +++ global_structures.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -97,9 +97,9 @@ class TargetGroup; class Target; -/* Stores "port info" which is TCP/UDP ports or RPC program ids */ +/* Stores "port info" which is TCP/UDP/SCTP ports or RPC program ids */ struct portinfo { - unsigned long portno; /* TCP/UDP port or RPC program id or IP protocool */ + unsigned long portno; /* TCP/UDP/SCTP port or RPC program id or IP protocool */ short trynum; int sd[3]; /* Socket descriptors for connect_scan */ struct timeval sent[3]; @@ -218,10 +218,12 @@ unsigned short *syn_ping_ports; unsigned short *ack_ping_ports; unsigned short *udp_ping_ports; + unsigned short *sctp_ping_ports; unsigned short *proto_ping_ports; int syn_ping_count; int ack_ping_count; int udp_ping_count; + int sctp_ping_count; int proto_ping_count; //the above fields are only used for host discovery //the fields below are only used for port scanning @@ -229,10 +231,12 @@ int tcp_count; unsigned short *udp_ports; int udp_count; + unsigned short *sctp_ports; + int sctp_count; unsigned short *prots; int prot_count; }; -typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype; +typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE, REF_TRACEROUTE}stype; #endif /*GLOBAL_STRUCTURES_H */ Index: targets.cc =================================================================== --- targets.cc (.../nmap) (revision 13362) +++ targets.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -483,7 +483,7 @@ 3) We are doing a raw-mode portscan or osscan OR 4) We are on windows and doing ICMP ping */ if (o.isr00t && o.af() == AF_INET && - ((pingtype & (PINGTYPE_TCP|PINGTYPE_UDP|PINGTYPE_PROTO|PINGTYPE_ARP)) || o.RawScan() + ((pingtype & (PINGTYPE_TCP|PINGTYPE_UDP|PINGTYPE_SCTP_INIT|PINGTYPE_PROTO|PINGTYPE_ARP)) || o.RawScan() #ifdef WIN32 || (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS)) #endif // WIN32 Index: services.cc =================================================================== --- services.cc (.../nmap) (revision 13362) +++ services.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -131,6 +131,7 @@ extern NmapOps o; static int numtcpports = 0; static int numudpports = 0; +static int numsctpports = 0; static std::map service_table; static std::list services_by_ratio; static int services_initialized = 0; @@ -241,6 +242,8 @@ numtcpports++; } else if (strncasecmp(proto, "udp", 3) == 0) { numudpports++; + } else if (strncasecmp(proto, "sctp", 4) == 0) { + numsctpports++; } else if (strncasecmp(proto, "ddp", 3) == 0) { /* ddp is some apple thing...we don't "do" that */ } else if (strncasecmp(proto, "divert", 6) == 0) { @@ -300,6 +303,10 @@ porttbl[ntohs(current.s_port)] |= SCAN_UDP_PORT; t++; } + if ((range_type & SCAN_SCTP_PORT) && strcmp(current.s_proto, "sctp") == 0) { + porttbl[ntohs(current.s_port)] |= SCAN_SCTP_PORT; + t++; + } } } @@ -352,6 +359,10 @@ for (i=0; iudp_count; i++) if (ntohs(serv->s_port) == ptsdata->udp_ports[i]) return true; + } else if (strcmp(serv->s_proto, "sctp") == 0) { + for (i=0; isctp_count; i++) + if (ntohs(serv->s_port) == ptsdata->sctp_ports[i]) + return true; } return false; @@ -368,10 +379,10 @@ // and return the N highest ratio ports (where N==level). // // This function doesn't support IP protocol scan so only call this -// function if o.TCPScan() || o.UDPScan() +// function if o.TCPScan() || o.UDPScan() || o.SCTPScan() void gettoppts(double level, char *portlist, struct scan_lists * ports) { - int ti=0, ui=0; + int ti=0, ui=0, si=0; struct scan_lists ptsdata = { 0 }; bool ptsdata_initialized = false; const struct service_node *current; @@ -420,6 +431,8 @@ ports->tcp_count++; else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0) ports->udp_count++; + else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0) + ports->sctp_count++; } else { break; } @@ -431,6 +444,9 @@ if (ports->udp_count) ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short)); + if (ports->sctp_count) + ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short)); + ports->prots = NULL; for (i = services_by_ratio.begin(); i != services_by_ratio.end(); i++) { @@ -442,6 +458,8 @@ ports->tcp_ports[ti++] = ntohs(current->s_port); else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0) ports->udp_ports[ui++] = ntohs(current->s_port); + else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0) + ports->sctp_ports[si++] = ntohs(current->s_port); } else { break; } @@ -458,6 +476,10 @@ ports->udp_count = MIN((int) level, numudpports); ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short)); } + if (o.SCTPScan()) { + ports->sctp_count = MIN((int) level, numsctpports); + ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short)); + } ports->prots = NULL; @@ -469,10 +491,13 @@ ports->tcp_ports[ti++] = ntohs(current->s_port); else if (o.UDPScan() && strcmp(current->s_proto, "udp") == 0 && ui < ports->udp_count) ports->udp_ports[ui++] = ntohs(current->s_port); + else if (o.SCTPScan() && strcmp(current->s_proto, "sctp") == 0 && si < ports->sctp_count) + ports->sctp_ports[si++] = ntohs(current->s_port); } if (ti < ports->tcp_count) ports->tcp_count = ti; if (ui < ports->udp_count) ports->udp_count = ui; + if (si < ports->sctp_count) ports->sctp_count = si; } else fatal("Argument to gettoppts (%g) should be a positive ratio below 1 or an integer of 1 or higher", level); @@ -487,9 +512,12 @@ if (ports->udp_count > 1) qsort(ports->udp_ports, ports->udp_count, sizeof(unsigned short), &port_compare); + if (ports->sctp_count > 1) + qsort(ports->sctp_ports, ports->sctp_count, sizeof(unsigned short), &port_compare); + if (o.debugging && level < 1) - log_write(LOG_STDOUT, "PORTS: Using ports open on %g%% or more average hosts (TCP:%d, UDP:%d)\n", level*100, ports->tcp_count, ports->udp_count); + log_write(LOG_STDOUT, "PORTS: Using ports open on %g%% or more average hosts (TCP:%d, UDP:%d, SCTP:%d)\n", level*100, ports->tcp_count, ports->udp_count, ports->sctp_count); else if (o.debugging && level >= 1) - log_write(LOG_STDOUT, "PORTS: Using top %d ports found open (TCP:%d, UDP:%d)\n", (int) level, ports->tcp_count, ports->udp_count); + log_write(LOG_STDOUT, "PORTS: Using top %d ports found open (TCP:%d, UDP:%d, SCTP:%d)\n", (int) level, ports->tcp_count, ports->udp_count, ports->sctp_count); } Index: services.h =================================================================== --- services.h (.../nmap) (revision 13362) +++ services.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -111,7 +111,8 @@ */ #define SCAN_TCP_PORT (1 << 0) #define SCAN_UDP_PORT (1 << 1) -#define SCAN_PROTOCOLS (1 << 2) +#define SCAN_SCTP_PORT (1 << 2) +#define SCAN_PROTOCOLS (1 << 3) int addportsfromservmask(char *mask, u8 *porttbl, int range_type); struct servent *nmap_getservbyport(int port, const char *proto); Index: nse_nmaplib.cc =================================================================== --- nse_nmaplib.cc (.../nmap) (revision 13362) +++ nse_nmaplib.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -14,6 +14,7 @@ #include "nmap_rpc.h" #include "nmap_dns.h" #include "osscan.h" +#include "protocols.h" /* #include "output.h" UNNECESSARY?? */ @@ -115,7 +116,7 @@ lua_pushstring(L, sd.name); lua_setfield(L, -2, "service"); - lua_pushstring(L, (port->proto == IPPROTO_TCP)? "tcp": "udp"); + lua_pushstring(L, IPPROTO2STR(port->proto)); lua_setfield(L, -2, "protocol"); lua_newtable(L); @@ -315,7 +316,8 @@ portno = (int) lua_tointeger(L, -2); protocol = strcmp(lua_tostring(L, -1), "tcp") == 0 ? IPPROTO_TCP : strcmp(lua_tostring(L, -1), "udp") == 0 ? IPPROTO_UDP : - luaL_error(L, "port 'protocol' field must be \"udp\" or \"tcp\""); + strcmp(lua_tostring(L, -1), "sctp") == 0 ? IPPROTO_SCTP : + luaL_error(L, "port 'protocol' field must be \"udp\", \"sctp\" or \"tcp\""); while ((port = target->ports.nextPort(port, protocol, PORT_UNKNOWN)) != NULL) if (port->portno == portno) break; Index: nmap.cc =================================================================== --- nmap.cc (.../nmap) (revision 13362) +++ nmap.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -216,7 +216,7 @@ " -sL: List Scan - simply list targets to scan\n" " -sP: Ping Scan - go no further than determining if host is online\n" " -PN: Treat all hosts as online -- skip host discovery\n" - " -PS/PA/PU[portlist]: TCP SYN/ACK or UDP discovery to given ports\n" + " -PS/PA/PU/PY[portlist]: TCP SYN/ACK, UDP or SCTP discovery to given ports\n" " -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes\n" " -PO[protocol list]: IP Protocol Ping\n" " -n/-R: Never do DNS resolution/Always resolve [default: sometimes]\n" @@ -229,6 +229,7 @@ " -sN/sF/sX: TCP Null, FIN, and Xmas scans\n" " --scanflags : Customize TCP scan flags\n" " -sI : Idle scan\n" + " -sY/sZ: SCTP INIT/COOKIE-ECHO scans\n" " -sO: IP protocol scan\n" " -b : FTP bounce scan\n" "PORT SPECIFICATION AND SCAN ORDER:\n" @@ -280,7 +281,8 @@ " --ip-options : Send packets with specified ip options\n" " --ttl : Set IP time-to-live field\n" " --spoof-mac : Spoof your MAC address\n" - " --badsum: Send packets with a bogus TCP/UDP checksum\n" + " --badsum: Send packets with a bogus TCP/UDP/SCTP checksum\n" + " --adler32: Use deprecated Adler32 instead of CRC32C for SCTP checksums\n" "OUTPUT:\n" " -oN/-oX/-oS/-oG : Output scan in normal, XML, s| 0); } } + else if (*optarg == 'Y') { + if (ports.sctp_ping_count > 0) + fatal("Only one -PY option is allowed. Combine port ranges with commas."); + o.pingtype |= (PINGTYPE_SCTP_INIT); + if (*(optarg + 1) != '\0') { + getpts_simple(optarg + 1, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count); + if (ports.sctp_ping_count <= 0) + fatal("Bogus argument to -PY: %s", optarg + 1); + } else { + getpts_simple(DEFAULT_SCTP_PROBE_PORT_SPEC, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count); + assert(ports.sctp_ping_count > 0); + } + } else if (*optarg == 'B') { if (ports.ack_ping_count > 0) fatal("Only one -PB, -PA, or -PT option is allowed. Combine port ranges with commas."); @@ -1186,6 +1204,8 @@ case 'V': o.servicescan = 1; break; case 'W': o.windowscan = 1; break; case 'X': o.xmasscan++; break; + case 'Y': o.sctpinitscan = 1; break; + case 'Z': o.sctpcookieechoscan = 1; break; default: error("Scantype %c not supported\n",*p); printusage(argv[0], -1); break; } p++; @@ -1213,6 +1233,7 @@ o.setMaxRttTimeout(1250); o.setInitialRttTimeout(500); o.setMaxTCPScanDelay(10); + o.setMaxSCTPScanDelay(10); o.setMaxRetransmissions(6); } else if (*optarg == '5' || (strcasecmp(optarg, "Insane") == 0)) { o.timing_level = 5; @@ -1220,7 +1241,7 @@ o.setMaxRttTimeout(300); o.setInitialRttTimeout(250); o.host_timeout = 900000; - o.setMaxTCPScanDelay(5); + o.setMaxSCTPScanDelay(5); o.setMaxRetransmissions(2); } else { fatal("Unknown timing mode (-T argument). Use either \"Paranoid\", \"Sneaky\", \"Polite\", \"Normal\", \"Aggressive\", \"Insane\" or a number from 0 (Paranoid) to 5 (Insane)"); @@ -1252,6 +1273,7 @@ o.scan_delay = pre_scan_delay; if (o.scan_delay > o.maxTCPScanDelay()) o.setMaxTCPScanDelay(o.scan_delay); if (o.scan_delay > o.maxUDPScanDelay()) o.setMaxUDPScanDelay(o.scan_delay); + if (o.scan_delay > o.maxSCTPScanDelay()) o.setMaxSCTPScanDelay(o.scan_delay); o.max_parallelism = 1; if(pre_max_parallelism != -1) fatal("You can't use --max-parallelism with --scan-delay."); @@ -1259,6 +1281,7 @@ if (pre_max_scan_delay != -1) { o.setMaxTCPScanDelay(pre_max_scan_delay); o.setMaxUDPScanDelay(pre_max_scan_delay); + o.setMaxSCTPScanDelay(pre_max_scan_delay); } if (pre_init_rtt_timeout != -1) o.setInitialRttTimeout(pre_init_rtt_timeout); if (pre_min_rtt_timeout != -1) o.setMinRttTimeout(pre_min_rtt_timeout); @@ -1347,7 +1370,7 @@ } // Uncomment the following line to use the common lisp port spec test suite - //printf("port spec: (%d %d %d)\n", ports.tcp_count, ports.udp_count, ports.prot_count); exit(0); + //printf("port spec: (%d %d %d %d)\n", ports.tcp_count, ports.udp_count, ports.stcp_count, ports.prot_count); exit(0); #ifdef WIN32 if (o.sendpref & PACKET_SEND_IP) { @@ -1408,6 +1431,8 @@ */ if ((o.TCPScan()) && ports.tcp_count == 0) error("WARNING: a TCP scan type was requested, but no tcp ports were specified. Skipping this scan type."); + if (o.SCTPScan() && ports.sctp_count == 0) + error("WARNING: a SCTP scan type was requested, but no sctp ports were specified. Skipping this scan type."); if (o.UDPScan() && ports.udp_count == 0) error("WARNING: UDP scan was requested, but no udp ports were specified. Skipping this scan type."); if (o.ipprotscan && ports.prot_count == 0) @@ -1504,7 +1529,7 @@ /* Before we randomize the ports scanned, lets output them to machine parseable output */ if (o.verbose) - output_ports_to_machine_parseable_output(&ports, o.TCPScan(), o.udpscan, o.ipprotscan); + output_ports_to_machine_parseable_output(&ports, o.TCPScan(), o.UDPScan(), o.SCTPScan(), o.ipprotscan); /* more fakeargv junk, BTW malloc'ing extra space in argv[0] doesn't work */ if (quashargv) { @@ -1534,7 +1559,7 @@ log_write(LOG_PLAIN, "--------------- Timing report ---------------\n"); log_write(LOG_PLAIN, " hostgroups: min %d, max %d\n", o.minHostGroupSz(), o.maxHostGroupSz()); log_write(LOG_PLAIN, " rtt-timeouts: init %d, min %d, max %d\n", o.initialRttTimeout(), o.minRttTimeout(), o.maxRttTimeout()); - log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay()); + log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d, SCTP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay(), o.maxSCTPScanDelay()); log_write(LOG_PLAIN, " parallelism: min %d, max %d\n", o.min_parallelism, o.max_parallelism); log_write(LOG_PLAIN, " max-retries: %d, host-timeout: %ld\n", o.getMaxRetransmissions(), o.host_timeout); log_write(LOG_PLAIN, " min-rate: %g, max-rate: %g\n", o.min_packet_send_rate, o.max_packet_send_rate); @@ -1548,6 +1573,8 @@ PortList::initializePortMap(IPPROTO_TCP, ports.tcp_ports, ports.tcp_count); if (o.UDPScan()) PortList::initializePortMap(IPPROTO_UDP, ports.udp_ports, ports.udp_count); + if (o.SCTPScan()) + PortList::initializePortMap(IPPROTO_SCTP, ports.sctp_ports, ports.sctp_count); if (randomize) { if (ports.tcp_count) { @@ -1557,6 +1584,8 @@ } if (ports.udp_count) shortfry(ports.udp_ports, ports.udp_count); + if (ports.sctp_count) + shortfry(ports.sctp_ports, ports.sctp_count); if (ports.prot_count) shortfry(ports.prots, ports.prot_count); } @@ -1763,6 +1792,12 @@ if (o.connectscan) ultra_scan(Targets, &ports, CONNECT_SCAN); + if (o.sctpinitscan) + ultra_scan(Targets, &ports, SCTP_INIT_SCAN); + + if (o.sctpcookieechoscan) + ultra_scan(Targets, &ports, SCTP_COOKIE_ECHO_SCAN); + if (o.ipprotscan) ultra_scan(Targets, &ports, IPPROT_SCAN); @@ -2123,12 +2158,14 @@ u8 *porttbl; int range_type = 0; int portwarning = 0; - int i, tcpi, udpi, proti; + int i, tcpi, udpi, sctpi, proti; if (o.TCPScan()) range_type |= SCAN_TCP_PORT; if (o.UDPScan()) range_type |= SCAN_UDP_PORT; + if (o.SCTPScan()) + range_type |= SCAN_SCTP_PORT; if (o.ipprotscan) range_type |= SCAN_PROTOCOLS; @@ -2137,22 +2174,25 @@ getpts_aux(origexpr, // Pass on the expression 0, // Don't start off nested porttbl, // Our allocated port table - range_type, // Defaults to TCP/UDP/Protos + range_type, // Defaults to TCP/UDP/SCTP/Protos &portwarning); // No, we haven't warned them about dup ports yet ports->tcp_count = 0; ports->udp_count = 0; + ports->sctp_count = 0; ports->prot_count = 0; for(i = 0; i <= 65535; i++) { if (porttbl[i] & SCAN_TCP_PORT) ports->tcp_count++; if (porttbl[i] & SCAN_UDP_PORT) ports->udp_count++; + if (porttbl[i] & SCAN_SCTP_PORT) + ports->sctp_count++; if (porttbl[i] & SCAN_PROTOCOLS && i < 256) ports->prot_count++; } - if (range_type != 0 && 0 == (ports->tcp_count + ports->udp_count + ports->prot_count)) + if (range_type != 0 && 0 == (ports->tcp_count + ports->udp_count + ports->sctp_count + ports->prot_count)) fatal("No ports specified -- If you really don't want to scan any ports use ping scan..."); if (ports->tcp_count) { @@ -2161,15 +2201,20 @@ if (ports->udp_count) { ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short)); } + if (ports->sctp_count) { + ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short)); + } if (ports->prot_count) { ports->prots = (unsigned short *)safe_zalloc(ports->prot_count * sizeof(unsigned short)); } - for(i=tcpi=udpi=proti=0; i <= 65535; i++) { + for(i=tcpi=udpi=sctpi=proti=0; i <= 65535; i++) { if (porttbl[i] & SCAN_TCP_PORT) ports->tcp_ports[tcpi++] = i; if (porttbl[i] & SCAN_UDP_PORT) ports->udp_ports[udpi++] = i; + if (porttbl[i] & SCAN_SCTP_PORT) + ports->sctp_ports[sctpi++] = i; if (porttbl[i] & SCAN_PROTOCOLS && i < 256) ports->prots[proti++] = i; } @@ -2179,7 +2224,7 @@ /* This function is like getpts except it only allocates space for and stores values into one unsigned short array, instead of an entire scan_lists struct - For that reason, T:, U:, and P: restrictions are not allowed and only one + For that reason, T:, U:, S: and P: restrictions are not allowed and only one bit in range_type may be set. */ void getpts_simple(const char *origexpr, int range_type, unsigned short **list, int *count) { @@ -2251,6 +2296,11 @@ range_type = SCAN_UDP_PORT; continue; } + if (*current_range == 'S' && *++current_range == ':') { + current_range++; + range_type = SCAN_SCTP_PORT; + continue; + } if (*current_range == 'P' && *++current_range == ':') { current_range++; range_type = SCAN_PROTOCOLS; @@ -2368,6 +2418,10 @@ nmap_getservbyport(htons(rangestart), "udp")) { porttbl[rangestart] |= SCAN_UDP_PORT; } + if ((range_type & SCAN_SCTP_PORT) && + nmap_getservbyport(htons(rangestart), "sctp")) { + porttbl[rangestart] |= SCAN_SCTP_PORT; + } if ((range_type & SCAN_PROTOCOLS) && nmap_getprotbynum(htons(rangestart))) { porttbl[rangestart] |= SCAN_PROTOCOLS; @@ -2399,6 +2453,7 @@ void free_scan_lists(struct scan_lists *ports) { if (ports->tcp_ports) free(ports->tcp_ports); if (ports->udp_ports) free(ports->udp_ports); + if (ports->sctp_ports) free(ports->sctp_ports); if (ports->prots) free(ports->prots); if (ports->syn_ping_ports) free(ports->syn_ping_ports); if (ports->ack_ping_ports) free(ports->ack_ping_ports); @@ -2500,6 +2555,8 @@ case CONNECT_SCAN: return "Connect Scan"; break; case NULL_SCAN: return "NULL Scan"; break; case WINDOW_SCAN: return "Window Scan"; break; + case SCTP_INIT_SCAN: return "SCTP INIT Scan"; break; + case SCTP_COOKIE_ECHO_SCAN: return "SCTP COOKIE-ECHO Scan"; break; case RPC_SCAN: return "RPCGrind Scan"; break; case MAIMON_SCAN: return "Maimon Scan"; break; case IPPROT_SCAN: return "IPProto Scan"; break; Index: nmap.h =================================================================== --- nmap.h (.../nmap) (revision 13362) +++ nmap.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -218,6 +218,11 @@ #include #endif +/* For systems without SCTP in netinet/in.h, such as MacOS X */ +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + /* Keep assert() defined for security reasons */ #undef NDEBUG @@ -272,6 +277,9 @@ #define DEFAULT_UDP_PROBE_PORT_SPEC "31338" /* The port UDP probes (esp. "ping" probes) go to if unspecified by user */ +#define DEFAULT_SCTP_PROBE_PORT_SPEC "80" /* The port SCTP probes go to + if unspecified by + user */ #define DEFAULT_PROTO_PROBE_PORT_SPEC "1,2,4" /* The IPProto ping probes to use if unspecified by user */ @@ -291,6 +299,10 @@ #define MAX_UDP_SCAN_DELAY 1000 #endif +#ifndef MAX_SCTP_SCAN_DELAY +#define MAX_SCTP_SCAN_DELAY 1000 +#endif + /* Maximum number of extra hostnames, OSs, and devices, we consider when outputing the extra service info fields */ #define MAX_SERVICE_INFO_FIELDS 5 @@ -340,6 +352,7 @@ #define PINGTYPE_UDP 512 #define PINGTYPE_ARP 1024 #define PINGTYPE_PROTO 2048 +#define PINGTYPE_SCTP_INIT 4096 #define DEFAULT_PING_TYPES PINGTYPE_TCP|PINGTYPE_TCP_USE_ACK|PINGTYPE_ICMP_PING Index: scan_engine.h =================================================================== --- scan_engine.h (.../nmap) (revision 13362) +++ scan_engine.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -107,6 +107,11 @@ u16 dport; }; +struct probespec_sctpdata { + u16 dport; + u8 chunktype; +}; + struct probespec_icmpdata { u8 type; u8 code; @@ -119,6 +124,7 @@ #define PS_ICMP 4 #define PS_ARP 5 #define PS_CONNECTTCP 6 +#define PS_SCTP 7 /* The size of this structure is critical, since there can be tens of thousands of them stored together ... */ @@ -130,6 +136,7 @@ union { struct probespec_tcpdata tcp; /* If type is PS_TCP or PS_CONNECTTCP. */ struct probespec_udpdata udp; /* PS_UDP */ + struct probespec_sctpdata sctp; /* PS_SCTP */ struct probespec_icmpdata icmp; /* PS_ICMP */ /* Nothing needed for PS_ARP, since src mac and target IP are avail from target structure anyway */ Index: NmapOps.cc =================================================================== --- NmapOps.cc (.../nmap) (revision 13362) +++ NmapOps.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -238,6 +238,7 @@ max_host_group_sz = 100000; // don't want to be restrictive unless user sets max_tcp_scan_delay = MAX_TCP_SCAN_DELAY; max_udp_scan_delay = MAX_UDP_SCAN_DELAY; + max_sctp_scan_delay = MAX_SCTP_SCAN_DELAY; max_ips_to_scan = 0; extra_payload_length = 0; extra_payload = NULL; @@ -258,6 +259,8 @@ listscan = pingscan = allowall = ackscan = bouncescan = connectscan = 0; rpcscan = nullscan = xmasscan = fragscan = synscan = windowscan = 0; maimonscan = idlescan = finscan = udpscan = ipprotscan = noresolve = 0; + sctpinitscan = 0; + sctpcookieechoscan = 0; append_output = 0; memset(logfd, 0, sizeof(FILE *) * LOG_NUM_FILES); ttl = -1; @@ -266,6 +269,7 @@ gettimeofday(&start_time, NULL); pTrace = vTrace = false; reason = false; + adler32 = false; if (datadir) free(datadir); datadir = NULL; if (xsl_stylesheet) free(xsl_stylesheet); @@ -305,6 +309,10 @@ sourcesocklen = 0; } +bool NmapOps::SCTPScan() { + return sctpinitscan|sctpcookieechoscan; +} + bool NmapOps::TCPScan() { return ackscan|bouncescan|connectscan|finscan|idlescan|maimonscan|nullscan|synscan|windowscan|xmasscan; } @@ -318,9 +326,9 @@ IPv6 is being used. It will return false in those cases where a RawScan is not neccessarily used. */ bool NmapOps::RawScan() { - if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan) + if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|osscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan) return true; - if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP)) + if (pingtype & (PINGTYPE_ICMP_PING|PINGTYPE_ICMP_MASK|PINGTYPE_ICMP_TS|PINGTYPE_TCP_USE_ACK|PINGTYPE_UDP|PINGTYPE_SCTP_INIT)) return true; return false; @@ -336,11 +344,11 @@ /* Insure that at least one scantype is selected */ - if (TCPScan() + UDPScan() + ipprotscan + listscan + pingscan == 0) { + if (TCPScan() + UDPScan() + SCTPScan() + ipprotscan + listscan + pingscan == 0) { if (isr00t && af() == AF_INET) synscan++; else connectscan++; - // if (verbose) error("No tcp, udp, or ICMP scantype specified, assuming %s scan. Use -sP if you really don't want to portscan (and just want to see what hosts are up).", synscan? "SYN Stealth" : "vanilla tcp connect()"); + // if (verbose) error("No TCP, UDP, SCTP or ICMP scantype specified, assuming %s scan. Use -sP if you really don't want to portscan (and just want to see what hosts are up).", synscan? "SYN Stealth" : "vanilla tcp connect()"); } if (pingtype != PINGTYPE_NONE && spoofsource) { @@ -364,11 +372,15 @@ fatal("Sorry, UDP Ping (-PU) only works if you are root (because we need to read raw responses off the wire) and only for IPv4 (cause fyodor is too lazy right now to add IPv6 support and nobody has sent a patch)"); } + if ((pingtype & PINGTYPE_SCTP_INIT) && (!isr00t || af() != AF_INET)) { + fatal("Sorry, SCTP INIT Ping (-PY) only works if you are root (because we need to read raw responses off the wire) and only for IPv4 (cause fyodor is too lazy right now to add IPv6 support and nobody has sent a patch)"); + } + if ((pingtype & PINGTYPE_PROTO) && (!isr00t || af() != AF_INET)) { fatal("Sorry, IPProto Ping (-PO) only works if you are root (because we need to read raw responses off the wire) and only for IPv4"); } - if (ipprotscan + (TCPScan() || UDPScan()) + listscan + pingscan > 1) { + if (ipprotscan + (TCPScan() || UDPScan() || SCTPScan()) + listscan + pingscan > 1) { fatal("Sorry, the IPProtoscan, Listscan, and Pingscan (-sO, -sL, -sP) must currently be used alone rather than combined with other scan types."); } @@ -376,7 +388,7 @@ fatal("-PN (skip ping) is incompatable with -sP (ping scan). If you only want to enumerate hosts, try list scan (-sL)"); } - if (pingscan && (TCPScan() || UDPScan() || ipprotscan || listscan)) { + if (pingscan && (TCPScan() || UDPScan() || SCTPScan() || ipprotscan || listscan)) { fatal("Ping scan is not valid with any other scan types (the other ones all include a ping scan"); } @@ -394,7 +406,7 @@ /* We start with stuff users should not do if they are not root */ if (!isr00t) { - if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan) { + if (ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan) { fatal("You requested a scan type which requires %s.", privreq); } @@ -477,7 +489,7 @@ fatal("--min-rate=%g must be less than or equal to --max-rate=%g", min_packet_send_rate, max_packet_send_rate); } - if (af() == AF_INET6 && (generate_random_ips|numdecoys|osscan|bouncescan|fragscan|ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan)) { + if (af() == AF_INET6 && (generate_random_ips|numdecoys|osscan|bouncescan|fragscan|ackscan|finscan|idlescan|ipprotscan|maimonscan|nullscan|synscan|udpscan|windowscan|xmasscan|sctpinitscan|sctpcookieechoscan)) { fatal("Sorry -- IPv6 support is currently only available for connect() scan (-sT), ping scan (-sP), and list scan (-sL). OS detection, random targets and decoys are also not supported with IPv6. Further support is under consideration."); } Index: portreasons.cc =================================================================== --- portreasons.cc (.../nmap) (revision 13362) +++ portreasons.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -113,7 +113,8 @@ "unknown", "admin-prohibited", "unknown", "time-exceeded", "unknown", "unknown", "timestamp-reply", "unknown", "unknown", "unknown", "addressmask-reply", "no-ipid-change", "ipid-change", "arp-response", "tcp-response", - "no-response", "localhost-response", "script-set", "unknown-response","user-set" + "no-response", "init-ack", "abort", + "localhost-response", "script-set", "unknown-response","user-set" }; const char *reason_pl_text[ER_MAX+1]={ @@ -125,7 +126,8 @@ "unknowns", "admin-prohibiteds", "unknowns", "time-exceededs", "unknowns", "unknowns", "timestamp-replies", "unknowns", "unknowns", "unknowns", "addressmask-replies", "no-ipid-changes", "ipid-changes", "arp-responses", - "tcp-responses", "no-responses", "localhost-response", "script-set", "unknown-responses" + "tcp-responses", "no-responses", "init-acks", "aborts", + "localhost-response", "script-set", "unknown-responses" }; static void state_reason_summary_init(state_reason_summary_t *r) { @@ -246,7 +248,7 @@ Port *current = NULL; state_reason_summary_t *reason; unsigned int total = 0; - unsigned short proto = (o.ipprotscan) ? IPPROTO_IP : TCPANDUDP; + unsigned short proto = (o.ipprotscan) ? IPPROTO_IP : TCPANDUDPANDSCTP; if(head == NULL) return 0; Index: tcpip.cc =================================================================== --- tcpip.cc (.../nmap) (revision 13362) +++ tcpip.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -184,6 +184,8 @@ return uppercase? "TCP" : "tcp"; break; case IPPROTO_UDP: return uppercase? "UDP" : "udp"; break; + case IPPROTO_SCTP: + return uppercase? "SCTP" : "sctp"; break; case IPPROTO_IP: return uppercase? "IP" : "ip"; break; default: @@ -427,6 +429,7 @@ struct ip *ip = (struct ip *) packet; struct tcp_hdr *tcp = NULL; struct udp_hdr *udp = NULL; + struct sctp_hdr *sctp = NULL; char ipinfo[512]; char srchost[INET6_ADDRSTRLEN], dsthost[INET6_ADDRSTRLEN]; char *p; @@ -549,6 +552,14 @@ Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:%d > %s:%d %s", srchost, ntohs(udp->uh_sport), dsthost, ntohs(udp->uh_dport), ipinfo); + } else if (ip->ip_p == IPPROTO_SCTP && frag_off) { + Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:?? > %s:?? fragment %s (incomplete)", srchost, dsthost, ipinfo); + } else if (ip->ip_p == IPPROTO_SCTP) { + sctp = (struct sctp_hdr *) (packet + sizeof(struct ip)); + + Snprintf(protoinfo, sizeof(protoinfo), "SCTP %s:%d > %s:%d %s", + srchost, ntohs(sctp->sh_sport), dsthost, ntohs(sctp->sh_dport), + ipinfo); } else if (ip->ip_p == IPPROTO_ICMP && frag_off) { Snprintf(protoinfo, sizeof(protoinfo), "ICMP %s > %s fragment %s (incomplete)", srchost, dsthost, ipinfo); } else if (ip->ip_p == IPPROTO_ICMP) { @@ -577,6 +588,7 @@ if (pktlen + 8 < len) { tcp = (struct tcp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4)); udp = (struct udp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4)); + sctp = (struct sctp_hdr *) ((char *) ip2 + (ip2->ip_hl * 4)); } ip2dst = inet_ntoa(ip2->ip_dst); switch (ping->code) { @@ -594,6 +606,8 @@ Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(udp->uh_dport)); else if (ip2->ip_p == IPPROTO_TCP && tcp) Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(tcp->th_dport)); + else if (ip2->ip_p == IPPROTO_SCTP && sctp) + Snprintf(icmptype, sizeof icmptype, "port %u unreachable", ntohs(sctp->sh_dport)); else strcpy(icmptype, "port unreachable"); break; @@ -1761,6 +1775,69 @@ return res; } +/* Builds an SCTP packet (including an IP header) by packing the fields + with the given information. It allocates a new buffer to store the + packet contents, and then returns that buffer. The packet is not + actually sent by this function. Caller must delete the buffer when + finished with the packet. The packet length is returned in + packetlen, which must be a valid int pointer. */ +u8 *build_sctp_raw(const struct in_addr *source, const struct in_addr *victim, + int ttl, u16 ipid, u8 tos, bool df, + u8 *ipopt, int ipoptlen, + u16 sport, u16 dport, + u32 vtag, char *chunks, int chunkslen, + char *data, u16 datalen, u32 *outpacketlen) +{ + int packetlen = sizeof(struct ip) + ipoptlen + sizeof(struct sctp_hdr) + chunkslen + datalen; + u8 *packet = (u8 *) safe_malloc(packetlen); + struct ip *ip = (struct ip *) packet; + struct sctp_hdr *sctp = (struct sctp_hdr *) ((u8*)ip + sizeof(struct ip) + ipoptlen); + static int myttl = 0; + + /* check that required fields are there and not too silly */ + assert(victim); + assert(source); + assert(ipoptlen%4==0); + + /* Time to live */ + if (ttl == -1) { + myttl = (get_random_uint() % 23) + 37; + } else { + myttl = ttl; + } + + sctp->sh_sport = htons(sport); + sctp->sh_dport = htons(dport); + sctp->sh_sum = 0; + sctp->sh_vtag = htonl(vtag); + + if (chunks) + memcpy((u8*)sctp + sizeof(struct sctp_hdr), chunks, chunkslen); + + if (data) + memcpy((u8*)sctp + sizeof(struct sctp_hdr) + chunkslen, data, datalen); + + /* RFC 2960 originally defined Adler32 checksums, which was later + * revised to CRC32C in RFC 3309 and RFC 4960 respectively. + * Nmap uses CRC32C by default, unless --adler32 is given. */ + if (o.adler32) + sctp->sh_sum = htonl(nbase_adler32((unsigned char*)sctp, + sizeof(struct sctp_hdr) + chunkslen + datalen)); + else + sctp->sh_sum = htonl(nbase_crc32c((unsigned char*)sctp, + sizeof(struct sctp_hdr) + chunkslen + datalen)); + + if (o.badsum) + --sctp->sh_sum; + + fill_ip_raw(ip, packetlen, ipopt, ipoptlen, + tos, ipid, df?IP_DF:0, myttl, IPPROTO_SCTP, + source, victim); + + *outpacketlen = packetlen; + return packet; +} + /* Builds an IP packet (including an IP header) by packing the fields with the given information. It allocates a new buffer to store the packet contents, and then returns that buffer. The packet is not Index: portreasons.h =================================================================== --- portreasons.h (.../nmap) (revision 13362) +++ portreasons.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -139,7 +139,8 @@ ER_ADDRESSMASKREPLY=29, ER_NOIPIDCHANGE, ER_IPIDCHANGE, ER_ARPRESPONSE, ER_TCPRESPONSE, ER_NORESPONSE, - ER_LOCALHOST, ER_SCRIPT, ER_UNKNOWN, ER_USER, ER_MAX=ER_USER /* 39 */ + ER_INITACK, ER_ABORT, + ER_LOCALHOST, ER_SCRIPT, ER_UNKNOWN, ER_USER, ER_MAX=ER_USER /* 41 */ }; /* Be careful to update these values if any ICMP Index: tcpip.h =================================================================== --- tcpip.h (.../nmap) (revision 13362) +++ tcpip.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -525,6 +525,20 @@ char *data, u16 datalen, u32 *packetlen); +/* Builds an SCTP packet (including an IP header) by packing the fields + with the given information. It allocates a new buffer to store the + packet contents, and then returns that buffer. The packet is not + actually sent by this function. Caller must delete the buffer when + finished with the packet. The packet length is returned in + packetlen, which must be a valid int pointer. */ +u8 *build_sctp_raw(const struct in_addr *source, const struct in_addr *victim, + int ttl, u16 ipid, u8 tos, bool df, + u8* ipopt, int ipoptlen, + u16 sport, u16 dport, + u32 vtag, char *chunks, int chunkslen, + char *data, u16 datalen, + u32 *packetlen); + /* Builds an ICMP packet (including an IP header) by packing the fields with the given information. It allocates a new buffer to store the packet contents, and then returns that buffer. The Index: nse_nsock.cc =================================================================== --- nse_nsock.cc (.../nmap) (revision 13362) +++ nse_nsock.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -20,6 +20,7 @@ #include "NmapOps.h" #include "utils.h" #include "tcpip.h" +#include "protocols.h" #if HAVE_OPENSSL # include @@ -754,9 +755,7 @@ void l_nsock_trace(nsock_iod nsiod, const char *message, int direction) { int status; - int protocol; - int af; struct sockaddr local; @@ -773,7 +772,7 @@ &local, &remote, sizeof(sockaddr)); log_write(LOG_STDOUT, "%s: %s %s:%d %s %s:%d | %s\n", SCRIPT_ENGINE, - (protocol == IPPROTO_TCP) ? "TCP" : "UDP", + IPPROTO2STR_UC(protocol), inet_ntop_both(af, &local, ipstring_local), inet_port_both(af, &local), (direction == TO) ? ">" : "<", Index: portlist.h =================================================================== --- portlist.h (.../nmap) (revision 13362) +++ portlist.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -113,7 +113,8 @@ #define PORT_HIGHEST_STATE 9 /* ***IMPORTANT -- BUMP THIS UP WHEN STATES ARE ADDED *** */ -#define TCPANDUDP IPPROTO_MAX +#define TCPANDUDPANDSCTP IPPROTO_MAX +#define UDPANDSCTP (IPPROTO_MAX + 1) #define CONF_NONE 0 #define CONF_LOW 1 @@ -254,8 +255,9 @@ enum portlist_proto { // PortList Protocols PORTLIST_PROTO_TCP = 0, PORTLIST_PROTO_UDP = 1, - PORTLIST_PROTO_IP = 2, - PORTLIST_PROTO_MAX = 3 + PORTLIST_PROTO_SCTP = 2, + PORTLIST_PROTO_IP = 3, + PORTLIST_PROTO_MAX = 4 }; class PortList { @@ -281,12 +283,12 @@ first "afterthisport". Then supply the most recent returned port for each subsequent call. When no more matching ports remain, NULL will be returned. To restrict returned ports to just one protocol, - specify IPPROTO_TCP or IPPROTO_UDP for allowed_protocol. A TCPANDUDP - for allowed_protocol matches either. A 0 for allowed_state matches - all possible states. This function returns ports in numeric - order from lowest to highest, except that if you ask for both TCP & - UDP, every TCP port will be returned before we start returning UDP - ports */ + specify IPPROTO_TCP, IPPROTO_UDP or UPPROTO_SCTP for + allowed_protocol. A TCPANDUDPANDSCTP for allowed_protocol matches + either. A 0 for allowed_state matches all possible states. This + function returns ports in numeric order from lowest to highest, + except that if you ask for TCP, UDP & SCTP, all TCP ports will be + returned before we start returning UDP and finally SCTP ports */ Port *nextPort(Port *afterthisport, int allowed_protocol, int allowed_state); Index: nmap-services =================================================================== --- nmap-services (.../nmap) (revision 13362) +++ nmap-services (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -31,9 +31,11 @@ unknown 6/tcp 0.000502 echo 7/tcp 0.004855 echo 7/udp 0.024679 +echo 7/sctp unknown 8/tcp 0.000013 discard 9/tcp 0.003764 # sink null discard 9/udp 0.015733 # sink null +discard 9/sctp # sink null unknown 10/tcp 0.000063 systat 11/tcp 0.000075 # Active Users systat 11/udp 0.000577 # Active Users @@ -50,10 +52,13 @@ chargen 19/udp 0.015865 # ttytst source Character Generator ftp-data 20/tcp 0.001079 # File Transfer [Default Data] ftp-data 20/udp 0.001878 # File Transfer [Default Data] +ftp-data 20/sctp # File Transfer [Default Data] ftp 21/tcp 0.197667 # File Transfer [Control] ftp 21/udp 0.004844 # File Transfer [Control] +ftp 21/sctp # File Transfer [Control] ssh 22/tcp 0.182286 # Secure Shell Login ssh 22/udp 0.003905 # Secure Shell Login +ssh 22/sctp # Secure Shell Login telnet 23/tcp 0.221265 telnet 23/udp 0.006211 priv-mail 24/tcp 0.001154 # any private mail system @@ -153,6 +158,7 @@ finger 79/udp 0.000956 http 80/tcp 0.484143 # World Wide Web HTTP http 80/udp 0.035767 # World Wide Web HTTP +http 80/sctp # World Wide Web HTTP hosts2-ns 81/tcp 0.012056 # HOSTS2 Name Server hosts2-ns 81/udp 0.001005 # HOSTS2 Name Server xfer 82/tcp 0.002923 # XFER Utility @@ -323,6 +329,7 @@ nextstep 178/udp 0.000346 # NextStep Window Server bgp 179/tcp 0.010538 # Border Gateway Protocol bgp 179/udp 0.000494 # Border Gateway Protocol +bgp 179/sctp # Border Gateway Protocol ris 180/tcp 0.000038 # Intergraph ris 180/udp 0.000478 # Intergraph unify 181/tcp 0.000025 @@ -660,6 +667,7 @@ cvc_hostd 442/udp 0.000774 https 443/tcp 0.208669 # secure http (SSL) https 443/udp 0.010840 +https 443/sctp snpp 444/tcp 0.004466 # Simple Network Paging Protocol snpp 444/udp 0.000873 # Simple Network Paging Protocol microsoft-ds 445/tcp 0.056944 # SMB directly over IP @@ -1865,8 +1873,9 @@ unknown 1165/tcp 0.000152 unknown 1166/tcp 0.000152 unknown 1166/udp 0.000330 -unknown 1167/tcp 0.000076 -phone 1167/udp 0.000593 # conference calling +cisco-ipsla 1167/tcp 0.000076 # Cisco IP SLAs Control Protocol +cisco-ipsla 1167/udp 0.000593 # Cisco IP SLAs Control Protocol +cisco-ipsla 1167/sctp # Cisco IP SLAs Control Protocol unknown 1168/tcp 0.000076 unknown 1168/udp 0.000330 unknown 1169/tcp 0.000380 @@ -2586,7 +2595,9 @@ unknown 1811/tcp 0.000076 unknown 1812/tcp 0.000152 radius 1812/udp 0.053839 # RADIUS authentication protocol (RFC 2138) +radius 1812/sctp # RADIUS authentication protocol (RFC 2138) radacct 1813/udp 0.010429 # RADIUS accounting protocol (RFC 2139) +radacct 1813/sctp # RADIUS accounting protocol (RFC 2139) unknown 1814/udp 0.000330 unknown 1815/udp 0.000330 unknown 1818/udp 0.000330 @@ -2893,6 +2904,8 @@ msantipiracy 2222/udp 0.047902 # Microsoft Office OS X antipiracy network monitor unknown 2223/udp 0.010902 unknown 2224/tcp 0.000076 +rcip-itu 2225/tcp # Resource Connection Initiation Protocol +rcip-itu 2225/sctp # Resource Connection Initiation Protocol unknown 2226/udp 0.000330 ivs-video 2232/tcp 0.000151 # IVS Video default ivs-video 2232/udp 0.000626 # IVS Video default @@ -2998,6 +3011,7 @@ unknown 2418/tcp 0.000076 unknown 2418/udp 0.000330 unknown 2425/tcp 0.000076 +mgcp-gateway 2427/sctp unknown 2429/udp 0.000330 venus 2430/tcp 0.000050 venus 2430/udp 0.000478 @@ -3189,7 +3203,11 @@ unknown 2902/tcp 0.000076 extensisportfolio 2903/tcp 0.000100 # Portfolio Server by Extensis Product Group unknown 2903/udp 0.000330 -unknown 2904/udp 0.000330 +m2ua 2904/tcp # SIGTRAN M2UA +m2ua 2904/udp 0.000330 # SIGTRAN M2UA +m2ua 2904/sctp # SIGTRAN M2UA +m3ua 2905/tcp # SIGTRAN M3UA +m3ua 2905/sctp # SIGTRAN M3UA unknown 2908/tcp 0.000076 unknown 2908/udp 0.000661 unknown 2909/tcp 0.000228 @@ -3203,7 +3221,12 @@ unknown 2930/tcp 0.000076 unknown 2932/udp 0.000330 unknown 2940/udp 0.000330 -unknown 2944/udp 0.000330 +megaco-h248 2944/tcp # Megaco H-248 (Text) +megaco-h248 2944/udp 0.000330 # Megaco H-248 (Text) +megaco-h248 2944/sctp # Megaco H-248 (Text) +h248-binary 2945/tcp # Megaco H-248 (Binary) +h248-binary 2945/udp # Megaco H-248 (Binary) +h248-binary 2945/sctp # Megaco H-248 (Binary) wap-push 2948/udp 0.000791 # Windows Mobile devices often have this unknown 2950/udp 0.000330 unknown 2951/udp 0.000330 @@ -3275,6 +3298,7 @@ sj3 3086/tcp 0.000050 # SJ3 (kanji input) unknown 3089/tcp 0.000076 unknown 3094/udp 0.000661 +itu-bicc-stc 3097/sctp # ITU-T Q.1902.1/Q.2150.3 unknown 3099/udp 0.000330 unknown 3102/tcp 0.000076 unknown 3102/udp 0.000330 @@ -3488,6 +3512,7 @@ unknown 3546/tcp 0.000304 unknown 3551/tcp 0.000380 unknown 3555/udp 0.000330 +m2pa 3565/sctp # M2PA unknown 3569/udp 0.000991 unknown 3571/udp 0.000330 unknown 3573/udp 0.000330 @@ -3630,8 +3655,13 @@ unknown 3856/tcp 0.000076 unknown 3859/tcp 0.000152 unknown 3860/tcp 0.000076 -unknown 3863/tcp 0.000152 -unknown 3868/tcp 0.000076 +asap-tcp 3863/tcp 0.000152 # RSerPool ASAP (TCP) +asap-udp 3863/udp # RSerPool ASAP (UDP) +asap-sctp 3863/sctp # RSerPool ASAP (SCTP) +asap-tcp-tls 3864/tcp # RSerPool ASAP/TLS (TCP) +asap-sctp-tls 3864/sctp # RSerPool ASAP/TLS (SCTP) +diameter 3868/tcp 0.000076 # DIAMETER +diameter 3868/sctp # DIAMETER unknown 3869/tcp 0.000228 unknown 3869/udp 0.000330 unknown 3870/tcp 0.000152 @@ -4048,6 +4078,12 @@ unknown 4713/udp 0.000330 unknown 4726/udp 0.000330 unknown 4734/udp 0.000330 +ipfix 4739/tcp # IP Flow Info Export +ipfix 4739/udp # IP Flow Info Export +ipfix 4739/sctp # IP Flow Info Export +ipfixs 4740/tcp # IP Flow Info Export over TLS +ipfixs 4740/udp # IP Flow Info Export over DTLS +ipfixs 4740/sctp # IP Flow Info Export over DTLS unknown 4741/udp 0.000330 unknown 4743/udp 0.000330 unknown 4745/tcp 0.000076 @@ -4184,8 +4220,10 @@ unknown 5059/udp 0.000330 sip 5060/tcp 0.010613 # Session Initiation Protocol (SIP) sip 5060/udp 0.044350 # Session Initiation Protocol (SIP) -unknown 5061/tcp 0.000228 -unknown 5061/udp 0.000330 +sip 5060/sctp # Session Initiation Protocol (SIP) +sip-tls 5061/tcp 0.000228 # SIP-TLS +sip-tls 5061/udp 0.000330 # SIP-TLS +sip-tls 5061/sctp # SIP-TLS unknown 5063/tcp 0.000152 unknown 5066/tcp 0.000076 unknown 5068/udp 0.000330 @@ -4202,6 +4240,8 @@ unknown 5088/tcp 0.000076 unknown 5090/tcp 0.000076 unknown 5090/udp 0.000330 +car 5090/sctp # Candidate AR +cxtp 5091/sctp # Context Transfer Protocol unknown 5093/udp 0.003304 unknown 5094/udp 0.000330 unknown 5095/tcp 0.000076 @@ -4435,7 +4475,12 @@ nrpe 5666/tcp 0.006614 # Nagios NRPE unknown 5667/tcp 0.000076 unknown 5667/udp 0.000330 -unknown 5672/tcp 0.000076 +amqp 5672/tcp 0.000076 # AMQP +amqp 5672/udp # AMQP +amqp 5672/sctp # AMQP +v5ua 5675/tcp # V5UA application port +v5ua 5675/udp # V5UA application port +v5ua 5675/sctp # V5UA application port unknown 5678/tcp 0.000228 activesync 5679/tcp 0.000590 # Microsoft ActiveSync PDY synchronization canna 5680/tcp 0.000151 # Canna (Japanese Input) @@ -5133,6 +5178,7 @@ unknown 7613/udp 0.000661 unknown 7617/udp 0.000330 unknown 7625/tcp 0.000380 +simco 7626/sctp # SImple Middlebox COnfiguration (SIMCO) unknown 7627/tcp 0.000380 unknown 7628/tcp 0.000076 unknown 7630/udp 0.000330 @@ -5432,8 +5478,9 @@ unknown 8458/udp 0.000330 unknown 8468/udp 0.000330 unknown 8470/tcp 0.000076 -unknown 8471/tcp 0.000076 -unknown 8471/udp 0.000330 +pim-port 8471/tcp 0.000076 # PIM over Reliable Transport +pim-port 8471/udp 0.000330 # PIM over Reliable Transport +pim-port 8471/sctp # PIM over Reliable Transport unknown 8472/tcp 0.000076 unknown 8473/udp 0.000330 unknown 8474/tcp 0.000076 @@ -5624,7 +5671,9 @@ unknown 9080/tcp 0.000380 unknown 9080/udp 0.000330 unknown 9081/tcp 0.000228 -unknown 9084/tcp 0.000076 +aurora 9084/tcp 0.000076 # IBM AURORA Performance Visualizer +aurora 9084/udp # IBM AURORA Performance Visualizer +aurora 9084/sctp # IBM AURORA Performance Visualizer unknown 9085/udp 0.000330 unknown 9086/udp 0.000330 unknown 9088/udp 0.000330 @@ -5890,8 +5939,16 @@ unknown 9894/udp 0.000330 unknown 9897/udp 0.000661 unknown 9898/tcp 0.000228 -unknown 9900/tcp 0.000380 +sctp-tunneling 9899/udp # SCTP Tunneling +sctp-tunneling 9899/tcp # SCTP Tunneling +sctp-tunneling 9899/sctp # SCTP Tunneling +iua 9900/tcp 0.000380 # IUA +iua 9900/udp # IUA +iua 9900/sctp # IUA unknown 9901/tcp 0.000076 +enrp 9901/udp # ENRP server channel +enrp-sctp 9901/sctp # ENRP server channel +enrp-sctp-tls 9902/sctp # ENRP/TLS server channel unknown 9908/tcp 0.000076 unknown 9909/tcp 0.000076 unknown 9910/tcp 0.000076 @@ -6369,6 +6426,9 @@ unknown 11997/udp 0.000330 unknown 11998/udp 0.000330 unknown 11999/udp 0.000330 +wmereceiving 11997/sctp # WorldMailExpress +wmedistribution 11998/sctp # WorldMailExpress +wmereporting 11999/sctp # WorldMailExpress cce4x 12000/tcp 0.000427 # ClearCommerce Engine 4.x (www.clearcommerce.com) unknown 12000/udp 0.000661 unknown 12001/tcp 0.000076 @@ -6807,7 +6867,8 @@ unknown 13992/udp 0.000330 unknown 13996/udp 0.000330 unknown 14000/tcp 0.000380 -unknown 14001/tcp 0.000076 +sua 14001/tcp 0.000076 # SUA +sua 14001/sctp # SUA unknown 14006/udp 0.000330 unknown 14034/udp 0.000330 unknown 14035/udp 0.000330 @@ -8369,6 +8430,9 @@ unknown 20041/udp 0.000654 unknown 20045/udp 0.000654 unknown 20048/udp 0.000654 +nfsrdma 20049/tcp # Network File System (NFS) over RDMA +nfsrdma 20049/udp # Network File System (NFS) over RDMA +nfsrdma 20049/sctp # Network File System (NFS) over RDMA unknown 20052/tcp 0.000076 unknown 20055/udp 0.000654 unknown 20056/udp 0.000654 Index: nse_main.cc =================================================================== --- nse_main.cc (.../nmap) (revision 13362) +++ nse_main.cc (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -77,7 +77,8 @@ Port *current = NULL; lua_newtable(L); for (int i = 0; states[i] != PORT_HIGHEST_STATE; i++) - while ((current = plist->nextPort(current, TCPANDUDP, states[i])) != NULL) + while ((current = plist->nextPort(current, TCPANDUDPANDSCTP, + states[i])) != NULL) { lua_newtable(L); set_portinfo(L, current); Index: output.h =================================================================== --- output.h (.../nmap) (revision 13362) +++ output.h (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -171,7 +171,7 @@ in sequential order for space savings and easier to read output */ void output_ports_to_machine_parseable_output(struct scan_lists *ports, int tcpscan, int udpscan, - int protscan); + int sctpscan, int protscan); /* Similar to output_ports_to_machine_parseable_output, this function outputs the XML version, which is scaninfo records of each scan Index: CHANGELOG =================================================================== --- CHANGELOG (.../nmap) (revision 13362) +++ CHANGELOG (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -1,5 +1,38 @@ # Nmap Changelog ($Id$); -*-text-*- +o Fixed SCTP support to build on systems which do not define + IPPROTO_SCTP in netinet/in.h, such as MacOS X (at the time + of writing). [Daniel Roethlisberger] + +o Added SCTP COOKIE ECHO scan (-sZ). This SCTP scan type sends + a COOKIE ECHO chunk. Closed ports will return an ABORT, open + ports will not solicit any answer. [Daniel Roethlisberger] + +o Added support for packing COOKIE ECHO chunk headers to + libdnet-stripped. [Daniel Roethlisberger] + +o Added SCTP support to the traceroute feature. This allows the + --traceroute option to be used with SCTP INIT scans too. + [Daniel Roethlisberger] + +o Added support for packing SCTP INIT ACK, SHUTDOWN ACK and ABORT + chunk headers to libdnet-stripped. [Daniel Roethlisberger] + +o Added support for SCTP INIT ping probes. This allows the use + of SCTP for host discovery (-PY). [Daniel Roethlisberger] + +o Added experimental support for SCTP port scanning, consisting + of an initial implementation of SCTP INIT stealth scan (-sY) + and IP protocol scan for SCTP (-sO -p sctp), including the + ability to use Adler32 checksums (--adler32; RFC 2960) instead + of CRC32C (RFC 4960). [Daniel Roethlisberger] + +o Adding an initial list of 36 well-known SCTP ports to the + services database. [Daniel Roethlisberger] + +o Added basic, initial SCTP support to libdnet-stripped. Only + INIT chunks are supported so far. [Daniel Roethlisberger] + o Patched configure.ac to detect Lua include and library files in "lua5.1" subdirectories of /usr/include and the like. Apparently Debian puts them there. We still check the likes of Index: docs/refguide.xml =================================================================== --- docs/refguide.xml (.../nmap) (revision 13362) +++ docs/refguide.xml (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -322,12 +322,12 @@ ubiquitous ping tool. Users can skip the ping step entirely with a list scan () or by disabling ping (), or engage the network - with arbitrary combinations of multi-port TCP SYN/ACK, UDP, and - ICMP probes. The goal of these probes is to solicit responses - which demonstrate that an IP address is actually active (is being - used by a host or network device). On many networks, only a small - percentage of IP addresses are active at any given time. This is - particularly common with private address space + with arbitrary combinations of multi-port TCP SYN/ACK, UDP, SCTP + INIT and ICMP probes. The goal of these probes is to solicit + responses which demonstrate that an IP address is actually active + (is being used by a host or network device). On many networks, + only a small percentage of IP addresses are active at any given + time. This is particularly common with private address space such as 10.0.0.0/8. That network has 16 million IPs, but I have seen it used by companies with less than a thousand machines. Host discovery can find those machines in a sparsely allocated sea of @@ -644,6 +644,63 @@ + (SCTP INIT Ping) + + SCTP INIT ping + + + + This option sends an SCTP packet containing a minimal + INIT chunk. The default destination port is 80 (configurable + at compile time by changing + DEFAULT_SCTP_PROBE_PORT_SPEC + DEFAULT_SCTP_PROBE_PORT_SPEC + in nmap.h). + nmap.h + Alternate ports can be specified as a parameter. The syntax + is the same as for the + except that port type specifiers like + S: are not allowed. Examples are + and + . Note that there + can be no space between and the port + list. If multiple probes are specified they will be sent in + parallel. + + The INIT chunk suggests to the remote system that you + are attempting to establish an association. Normally the + destination port will be closed, and an ABORT chunk will be + sent back. If the port happens to be open, the target will + take the second step of an SCTP + four-way-handshakefour-way handshake + by responding with an INIT-ACK chunk. If the machine running + Nmap has a functional SCTP stack, then it tears down the + nascent association by responding with an ABORT chunk rather + than sending a COOKIE-ECHO chunk which would be the next step + in the four-way-handshake. The ABORT packet is sent by the + kernel of the machine running Nmap in response to the + unexpected INIT-ACK, not by Nmap itself. + + Nmap does not care whether the port is open or closed. + Either the ABORT or INIT-ACK response discussed previously tell + Nmap that the host is available and responsive. + + On Unix boxes, only the privileged user + rootprivileged users + is generally able to send and receive raw SCTP + packets.raw packets + Using SCTP INIT Pings is currently not possible for unprivileged + users.unprivileged userslimitations of + The same limitation applies to IPv6, which is currently not + supported for + SCTP INIT Ping.IPv6limitations of + + + + + + + ; ; (ICMP Ping Types) @@ -654,9 +711,9 @@ - In addition to the unusual TCP and UDP host discovery - types discussed previously, Nmap can send the standard - packets sent by the ubiquitous + In addition to the unusual TCP, UDP and SCTP host + discovery types discussed previously, Nmap can send the + standard packets sent by the ubiquitous ping program. Nmap sends an ICMP type 8 (echo request) packet to the target IP addresses, expecting a type 0 (echo reply) in return from available @@ -707,17 +764,17 @@ which sends IP packets with the specified protocol number set in their IP header. The protocol list takes the same format as do port lists in the - previously discussed TCP and UDP host discovery options. If - no protocols are specified, the default is to send multiple + previously discussed TCP, UDP and SCTP host discovery options. + If no protocols are specified, the default is to send multiple IP packets for ICMP (protocol 1), IGMP (protocol 2), and IP-in-IP (protocol 4). The default protocols can be configured at compile-time by changing DEFAULT_PROTO_PROBE_PORT_SPECDEFAULT_PROTO_PROBE_PORT_SPEC in nmap.h. - Note that for the ICMP, IGMP, TCP (protocol 6), and UDP - (protocol 17), the packets are sent with the proper protocol - headers while other protocols are sent with no additional data - beyond the IP header (unless the + Note that for the ICMP, IGMP, TCP (protocol 6), UDP + (protocol 17) and SCTP (protocol 132), the packets are sent + with the proper protocol headers while other protocols are + sent with no additional data beyond the IP header (unless the option is specified). This host discovery method looks for either responses @@ -897,11 +954,12 @@ open port state open An application is actively accepting TCP - connections or UDP packets on this port. Finding these is often the - primary goal of port scanning. Security-minded people know that - each open port is an avenue for attack. Attackers and pen-testers - want to exploit the open ports, while administrators try to close or - protect them with firewalls without thwarting legitimate users. + connections, UDP datagrams or SCTP associations on this port. + Finding these is often the primary goal of port scanning. + Security-minded people know that each open port is an avenue for attack. + Attackers and pen-testers want to exploit the open ports, while + administrators try to close or protect them with firewalls without + thwarting legitimate users. Open ports are also interesting for non-security scans because they show services available for use on the network. @@ -1017,8 +1075,10 @@ This section documents the dozen or so port scan techniques supported by Nmap. Only one method may be used at a time, -except that UDP scan () may be combined with any -one of the TCP scan types. As a memory aid, port scan type options +except that UDP scan () and any one of the +SCTP scan types (, ) +may be combined with any one of the TCP scan types. +As a memory aid, port scan type options are of the form , where C is a prominent character in the scan name, usually the first. The one exception to this is the deprecated @@ -1160,6 +1220,44 @@ + (SCTP INIT scan) + +SCTP INIT scan + + + + + SCTP +is a relatively new alternative to the TCP and UDP protocols, +combining most characteristics of TCP and UDP, and also adding +new features like multi-homing and multi-streaming. It is mostly +being used for SS7/SIGTRAN related services but has the potential +to be used for other applications as well. + +SCTP INIT scan is the SCTP equivalent of a TCP SYN scan. +It can be performed quickly, scanning thousands of ports per +second on a fast network not hampered by restrictive firewalls. +Like SYN scan, INIT scan is relatively unobtrusive and stealthy, +since it never completes SCTP associations. It also allows clear, +reliable differentiation between the open, +closed, and filtered +states. + +This technique is often referred to as half-open scanning, +because you don't open a full SCTP association. You send an INIT +chunk, as if you are going to open a real association and then wait +for a response. An INIT-ACK chunk indicates the port is listening +(open), while an ABORT chunk is indicative of a non-listener. If no +response is received after several retransmissions, the port is +marked as filtered. The port is also marked filtered if an ICMP +unreachable error (type 3, code 1, 2, 3, 9, 10, or 13) is +received. + + + + + + ; ; (TCP NULL, FIN, and Xmas scans) @@ -1349,6 +1447,35 @@ + (SCTP COOKIE ECHO scan) + +SCTP COOKIE ECHO scan + + + + +SCTP COOKIE ECHO scan is a more advanced SCTP scan. It takes +advantage of the fact that SCTP implementations should silently +drop packets containing COOKIE ECHO chunks on open ports, but +send an ABORT if the port is closed. + +The advantage of this scan type is that it is not as obvious a +port scan than an INIT scan. Also, there may be non-stateful +firewall rulesets blocking INIT chunks, but not COOKIE ECHO +chunks. Don't be fooled into thinking that this will make a +port scan invisible; a good IDS will be able to detect SCTP +COOKIE ECHO scans too. + +The downside is that SCTP COOKIE ECHO scans cannot differentiate +between open and filtered +ports, leaving you with the state open|filtered +in both cases. + + + + + + (idle scan) idle scan @@ -3141,7 +3268,7 @@ - Asks Nmap to use an invalid TCP or UDP checksum for + Asks Nmap to use an invalid TCP, UDP or SCTP checksum for packets sent to target hosts. Since virtually all host IP stacks properly drop these packets, any responses received are likely coming from a firewall or IDS that didn't bother to @@ -3150,6 +3277,31 @@ + + + (Use deprecated Adler32 instead of CRC32C for SCTP checksums) + + CRC32C checksum + Adler32 checksum + SCTP checksum + checksums + + + + + Asks Nmap to use the deprecated Adler32 algorithm + for calculating the SCTP checksum. If + is not given, CRC-32C (Castagnoli) is used. + RFC 2960 + originally defined Adler32 as checksum algorithm for SCTP; + RFC 4960 + later redefined the SCTP checksums to use CRC-32C. Current SCTP + implementations should be using CRC-32C, but in order to elicit + responses from old, legacy SCTP implementations, it may be + preferrable to use Adler32. + + + Index: docs/nmap.dtd =================================================================== --- docs/nmap.dtd (.../nmap) (revision 13362) +++ docs/nmap.dtd (.../nmap-exp/daniel/nmap-sctp) (revision 13366) @@ -58,11 +58,11 @@ - + - +