home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / nmap254b.zip / services.c < prev    next >
C/C++ Source or Header  |  2002-02-27  |  11KB  |  311 lines

  1.  
  2. /***********************************************************************/
  3. /* services.c -- Various functions relating to reading the             */
  4. /* nmap-services file and port <-> service mapping                     */
  5. /*                                                                     */
  6. /***********************************************************************/
  7. /*  The Nmap Security Scanner is (C) 1995-2001 Insecure.Com LLC. This  */
  8. /*  program is free software; you can redistribute it and/or modify    */
  9. /*  it under the terms of the GNU General Public License as published  */
  10. /*  by the Free Software Foundation; Version 2.  This guarantees your  */
  11. /*  right to use, modify, and redistribute this software under certain */
  12. /*  conditions.  If this license is unacceptable to you, we may be     */
  13. /*  willing to sell alternative licenses (contact sales@insecure.com). */
  14. /*                                                                     */
  15. /*  If you received these files with a written license agreement       */
  16. /*  stating terms other than the (GPL) terms above, then that          */
  17. /*  alternative license agreement takes precendence over this comment. */
  18. /*                                                                     */
  19. /*  Source is provided to this software because we believe users have  */
  20. /*  a right to know exactly what a program is going to do before they  */
  21. /*  run it.  This also allows you to audit the software for security   */
  22. /*  holes (none have been found so far).                               */
  23. /*                                                                     */
  24. /*  Source code also allows you to port Nmap to new platforms, fix     */
  25. /*  bugs, and add new features.  You are highly encouraged to send     */
  26. /*  your changes to fyodor@insecure.org for possible incorporation     */
  27. /*  into the main distribution.  By sending these changes to Fyodor or */
  28. /*  one the insecure.org development mailing lists, it is assumed that */
  29. /*  you are offering Fyodor the unlimited, non-exclusive right to      */
  30. /*  reuse, modify, and relicense the code.  This is important because  */
  31. /*  the inability to relicense code has caused devastating problems    */
  32. /*  for other Free Software projects (such as KDE and NASM).  Nmap     */
  33. /*  will always be available Open Source.  If you wish to specify      */
  34. /*  special license conditions of your contributions, just say so      */
  35. /*  when you send them.                                                */
  36. /*                                                                     */
  37. /*  This program is distributed in the hope that it will be useful,    */
  38. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of     */
  39. /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  */
  40. /*  General Public License for more details (                          */
  41. /*  http://www.gnu.org/copyleft/gpl.html ).                            */
  42. /*                                                                     */
  43. /***********************************************************************/
  44.  
  45. /* $Id: services.c,v 1.11 2001/09/25 08:20:00 fyodor Exp $ */
  46.  
  47.  
  48. #include "services.h"
  49.  
  50. extern struct ops o;
  51. static int services_initialized = 0;
  52. static int numtcpports = 0;
  53. static int numudpports = 0;
  54. static struct service_list *service_table[SERVICE_TABLE_SIZE];
  55.  
  56. static int nmap_services_init() {
  57.   char filename[512];
  58.   FILE *fp;
  59.   char servicename[128], proto[16];
  60.   u16 portno;
  61.   char *p;
  62.   char line[1024];
  63.   int lineno = 0;
  64.   struct service_list *current, *previous;
  65.   int res;
  66.  
  67.   if (nmap_fetchfile(filename, sizeof(filename), "nmap-services") == -1) {
  68. #ifndef WIN32
  69.     error("Unable to find nmap-services!  Resorting to /etc/services");
  70.     strcpy(filename, "/etc/services");
  71. #elif defined(__EMX__)
  72.         char *etcdir = getenv("ETC");
  73.  
  74.         if(etcdir)
  75.            sprintf(filename, "%s\\services");
  76.         else
  77.            strcpy(filename, "c:\\mptn\\etc\\services");
  78. #else
  79.     int len, wnt = GetVersion() < 0x80000000;
  80.     error("Unable to find nmap-services!  Resorting to /etc/services");
  81.     if(wnt)
  82.         len = GetSystemDirectory(filename, 480);    //    be safe
  83.     else
  84.         len = GetWindowsDirectory(filename, 480);    //    be safe
  85.     if(!len)
  86.         error("Get%sDirectory failed (%d) @#!#@\n",
  87.          wnt ? "System" : "Windows", GetLastError());
  88.     else
  89.     {
  90.         if(wnt)
  91.             strcpy(filename + len, "\\drivers\\etc\\services");
  92.         else
  93.             strcpy(filename + len, "\\services");
  94.     }
  95. #endif
  96.   }
  97.  
  98.   fp = fopen(filename, "r");
  99.   if (!fp) {
  100.     fatal("Unable to open %s for reading service information", filename);
  101.   }
  102.  
  103.   bzero(service_table, sizeof(service_table));
  104.   
  105.   while(fgets(line, sizeof(line), fp)) {
  106.     lineno++;
  107.     p = line;
  108.     while(*p && isspace((int) *p))
  109.       p++;
  110.     if (*p == '#')
  111.       continue;
  112.     res = sscanf(line, "%s %hu/%s", servicename, &portno, proto);
  113.     if (res !=3)
  114.       continue;
  115.     portno = htons(portno);
  116.  
  117.     /* Now we make sure our services doesn't have duplicates */
  118.     for(current = service_table[portno % SERVICE_TABLE_SIZE], previous = NULL;
  119.     current; current = current->next) {
  120.       if (portno == (u16) current->servent->s_port &&
  121.       strcasecmp(proto, current->servent->s_proto) == 0) {
  122.     if (o.debugging) {
  123.       error("Port %d proto %s is duplicated in services file %s", ntohs(portno), proto, filename);
  124.     }
  125.     break;
  126.       }
  127.       previous = current;
  128.     }
  129.     /* Current service in the file was a duplicate, get another one */
  130.     if (current)
  131.       continue;
  132.  
  133.     if (strncasecmp(proto, "tcp", 3) == 0) {
  134.       numtcpports++;
  135.     } else if (strncasecmp(proto, "udp", 3) == 0) {
  136.       numudpports++;
  137.     } else if (strncasecmp(proto, "ddp", 3) == 0) {
  138.       /* ddp is some apple thing...we don't "do" that */
  139.     } else if (strncasecmp(proto, "divert", 6) == 0) {
  140.       /* divert sockets are for freebsd's natd */
  141.     } else if (strncasecmp(proto, "#", 1) == 0) {
  142.       /* possibly misplaced comment, but who cares? */
  143.     } else {
  144.       if (o.debugging)
  145.     error("Unknown protocol (%s) on line %d of services file %s.", proto, lineno, filename);
  146.       continue;
  147.     }
  148.  
  149.     current = (struct service_list *) cp_alloc(sizeof(struct service_list));
  150.     current->servent = (struct servent *) cp_alloc(sizeof(struct servent));
  151.     current->next = NULL;
  152.     if (previous == NULL) {
  153.       service_table[portno % SERVICE_TABLE_SIZE] = current;
  154.     } else {
  155.       previous->next = current;
  156.     }
  157.     current->servent->s_name = cp_strdup(servicename);
  158.     current->servent->s_port = portno;
  159.     current->servent->s_proto = cp_strdup(proto);
  160.     current->servent->s_aliases = NULL;
  161.   }
  162.   fclose(fp);
  163.   services_initialized = 1;
  164.   return 0;
  165. }
  166.  
  167.  
  168. struct servent *nmap_getservbyport(int port, const char *proto) {
  169.   struct service_list *current;
  170.  
  171.   if (!services_initialized)
  172.     if (nmap_services_init() == -1)
  173.       return NULL;
  174.  
  175.   for(current = service_table[port % SERVICE_TABLE_SIZE];
  176.       current; current = current->next) {
  177.     if (((u16) port == (u16) current->servent->s_port) &&
  178.     strcmp(proto, current->servent->s_proto) == 0)
  179.       return current->servent;
  180.   }
  181.  
  182.   /* Couldn't find it ... oh well. */
  183.   return NULL;
  184.   
  185. }
  186.  
  187. /* Be default we do all ports 1-1024 as well as any higher ports
  188.    that are in the services file */
  189. struct scan_lists *getdefaultports(int tcpscan, int udpscan) {
  190.   int tcpportindex = 0;
  191.   int udpportindex = 0;
  192.   struct scan_lists *ports;
  193.   char usedports[65536];
  194.   struct service_list *current;
  195.   int bucket;
  196.   int tcpportsneeded = 0;
  197.   int udpportsneeded = 0;
  198.  
  199.   if (!services_initialized)
  200.     if (nmap_services_init() == -1)
  201.       fatal("Getfastports: Coudn't get port numbers");
  202.   
  203.   bzero(usedports, sizeof(usedports));
  204.   for(bucket = 1; bucket < 1025; bucket++) {  
  205.     if (tcpscan) {
  206.       usedports[bucket] |= SCAN_TCP_PORT;
  207.       tcpportsneeded++;
  208.     }
  209.     if (udpscan) {
  210.       usedports[bucket] |= SCAN_UDP_PORT;
  211.       udpportsneeded++;
  212.     }
  213.   }
  214.  
  215.   for(bucket = 0; bucket < SERVICE_TABLE_SIZE; bucket++) {  
  216.     for(current = service_table[bucket % SERVICE_TABLE_SIZE];
  217.     current; current = current->next) {
  218.       if (tcpscan &&
  219.       ! (usedports[ntohs(current->servent->s_port)] & SCAN_TCP_PORT) &&
  220.           ! strncmp(current->servent->s_proto, "tcp", 3)) {
  221.     usedports[ntohs(current->servent->s_port)] |= SCAN_TCP_PORT;
  222.     tcpportsneeded++;
  223.       }
  224.       if (udpscan && 
  225.       ! (usedports[ntohs(current->servent->s_port)] & SCAN_UDP_PORT) &&
  226.       !strncmp(current->servent->s_proto, "udp", 3)) {      
  227.     usedports[ntohs(current->servent->s_port)] |= SCAN_UDP_PORT;
  228.     udpportsneeded++;
  229.       }
  230.     }
  231.   }
  232.  
  233.   ports = (struct scan_lists *) cp_alloc(sizeof(struct scan_lists));
  234.   bzero(ports, sizeof(ports));
  235.   if (tcpscan) 
  236.     ports->tcp_ports = (unsigned short *) cp_alloc((tcpportsneeded+1) * sizeof(unsigned short));
  237.   if (udpscan) 
  238.     ports->udp_ports = (unsigned short *) cp_alloc((udpportsneeded+1) * sizeof(unsigned short));
  239.   ports->tcp_count= tcpportsneeded;
  240.   ports->udp_count= udpportsneeded;
  241.  
  242.   for(bucket = 1; bucket < 65536; bucket++) {
  243.     if (usedports[bucket] & SCAN_TCP_PORT) 
  244.       ports->tcp_ports[tcpportindex++] = bucket;
  245.     if (usedports[bucket] & SCAN_UDP_PORT) 
  246.       ports->udp_ports[udpportindex++] = bucket;
  247.   }
  248.   if (tcpscan) 
  249.     ports->tcp_ports[tcpportindex] = 0;
  250.   if (udpscan) 
  251.     ports->udp_ports[udpportindex] = 0;
  252. return ports;
  253. }
  254.  
  255. struct scan_lists *getfastports(int tcpscan, int udpscan) {
  256.   int tcpportindex = 0;
  257.   int udpportindex = 0;
  258.   struct scan_lists *ports;
  259.   char usedports[65536];
  260.   struct service_list *current;
  261.   int bucket;
  262.   int tcpportsneeded = 0;
  263.   int udpportsneeded = 0;
  264.  
  265.   if (!services_initialized)
  266.     if (nmap_services_init() == -1)
  267.       fatal("Getfastports: Coudn't get port numbers");
  268.   
  269.   bzero(usedports, sizeof(usedports));
  270.  
  271.   for(bucket = 0; bucket < SERVICE_TABLE_SIZE; bucket++) {  
  272.     for(current = service_table[bucket % SERVICE_TABLE_SIZE];
  273.     current; current = current->next) {
  274.       if (tcpscan  &&
  275.       ! (usedports[ntohs(current->servent->s_port)] & SCAN_TCP_PORT) &&
  276.       !strncmp(current->servent->s_proto, "tcp", 3)) {
  277.     usedports[ntohs(current->servent->s_port)] |= SCAN_TCP_PORT;
  278.     tcpportsneeded++;
  279.       }
  280.       if (udpscan &&
  281.       ! (usedports[ntohs(current->servent->s_port)] & SCAN_UDP_PORT) &&
  282.       !strncmp(current->servent->s_proto, "udp", 3)) {      
  283.     usedports[ntohs(current->servent->s_port)] |= SCAN_UDP_PORT;
  284.     udpportsneeded++;
  285.       }
  286.     }
  287.   }
  288.  
  289.   ports = (struct scan_lists *) cp_alloc(sizeof(struct scan_lists));
  290.   bzero(ports, sizeof(ports));
  291.   if (tcpscan) 
  292.     ports->tcp_ports = (unsigned short *) cp_alloc((tcpportsneeded+1) * sizeof(unsigned short));
  293.   if (udpscan)
  294.     ports->udp_ports = (unsigned short *) cp_alloc((udpportsneeded+1) * sizeof(unsigned short));
  295.   ports->tcp_count= tcpportsneeded;
  296.   ports->udp_count= udpportsneeded;
  297.  
  298.   for(bucket = 1; bucket < 65536; bucket++) {
  299.     if (usedports[bucket] & SCAN_TCP_PORT) 
  300.       ports->tcp_ports[tcpportindex++] = bucket;
  301.     if (usedports[bucket] & SCAN_UDP_PORT) 
  302.       ports->udp_ports[udpportindex++] = bucket;
  303.   }
  304.   if (tcpscan) 
  305.     ports->tcp_ports[tcpportindex] = 0;
  306.   if (udpscan) 
  307.     ports->udp_ports[udpportindex] = 0;
  308. return ports;
  309. }
  310.  
  311.