ADAPT / plugins / nmap / net_scan.c
net_scan.c
Raw
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "tool_runner.h"
#include "tokenize.h"
#include "arc_plugin_interface.h"

static char *parse_nmap_host_field(char *host_field, struct arc_model *a_m);
static void parse_nmap_status_field(char *status_field, struct arc_model *a_m, char *component_name);
static void parse_nmap_ports_field(char *ports_field, struct arc_model *a_m, char *component_name);
static void parse_nmap_port_field(char *port_field, struct arc_model *a_m, char *component_name);


static char *next_line(char *output, size_t *num_skip)
{
    char *line = output;
    size_t skip = 0;
    while(output[skip]!='\0')
    {
		skip++;
		if(output[skip]=='\n')
		{
			output[skip]='\0';
			skip++;
			break;
		}
    }
    *num_skip = skip;
    return line;
}

static void parse_nmap_grepable(char *line,struct arc_model *a_m)
{

    char *component_name = NULL;
    
    
    struct tokenizer tab_tokenizer;
    tokenizer_init(&tab_tokenizer, line, "\t");
    char *field_token = next_token(&tab_tokenizer);
    while(field_token)
    {

		char *field_type_pos = strchr(field_token, ':');
		char *field_type = strndup(field_token, field_type_pos-field_token);

		if(strcmp(field_type,"Host")==0)
		{
			if(component_name)
			{
				free(component_name);
			}
			component_name = parse_nmap_host_field(field_type_pos+1,a_m);
		}
		else if(strcmp(field_type,"Status")==0)
		{
			parse_nmap_status_field(field_type_pos+1,a_m,component_name);
		}
		else if(strcmp(field_type,"Ports")==0)
		{
			parse_nmap_ports_field(field_type_pos+1,a_m, component_name);
		}
		free(field_type);
		field_token = next_token(&tab_tokenizer);
    }
    tokenizer_cleanup(&tab_tokenizer);

    if(component_name)
    {
		free(component_name);
    }
}

static char *make_identifier(char *ip, char prefix)
{
    char *component_name = calloc(strlen(ip)+4,1);
    sprintf(component_name, "%c_%s",prefix,ip);
    for(size_t i=0;i<strlen(component_name);i++)
    {
		if(component_name[i] == '.')
		{
			component_name[i] = '_';
		}
    }

    return component_name;
}

static char *parse_nmap_host_field(char *host_field, struct arc_model *a_m)
{

    struct tokenizer whitespace_tok;
    tokenizer_init(&whitespace_tok,host_field, " ");
    char *ip = next_token(&whitespace_tok);
    if(!ip)
    {
		fprintf(stderr,"[nmap] No IP in nmap Host field!\n");
		return NULL;
    }

    char *component_name = make_identifier(ip,'T');
    arc_model_add_component(a_m,component_name);
    
    int nbytes = snprintf(NULL,0,"%s:IP",component_name);
    char ip_buff[nbytes+1];
    snprintf(ip_buff,nbytes+1,"%s:IP",component_name);
    arc_model_assign_property_str(a_m,ip_buff,ip);
    
    char *r_dns_name = next_token(&whitespace_tok);
    if(!r_dns_name  || strlen(r_dns_name) <= 2)
    {
		fprintf(stderr,"[nmap] No reverse DNS name or reverse DNS name is empty in nmap Host field!\n");
	
    }
    else
    {
		//do stuff with r_dns_name
		int nbytes = snprintf(NULL,0,"%s:RDNS",component_name);
		char rdns_buff[nbytes+1];
		snprintf(rdns_buff,nbytes+1,"%s:RDNS",component_name);
		arc_model_assign_property_str(a_m,rdns_buff,r_dns_name);
	
    }


    tokenizer_cleanup(&whitespace_tok);
    return component_name;
}


static void parse_nmap_status_field(char *status_field, struct arc_model *a_m, char *component_name)
{
    char *status = status_field+1;
    int nbytes = snprintf(NULL,0,"%s:Status",component_name);
    char buff[nbytes+1];
    snprintf(buff,nbytes+1,"%s:Status",component_name);
    arc_model_assign_property_str(a_m,buff,status);
}


static void parse_nmap_ports_field(char *ports_field, struct arc_model *a_m, char *component_name)
{
    struct tokenizer commaspace_tok;
    tokenizer_init(&commaspace_tok, ports_field,",");
    char *port_info = next_token(&commaspace_tok);

    int num_ports = 0;
    while(port_info)
    {
		parse_nmap_port_field(port_info+1, a_m, component_name);
		port_info = next_token(&commaspace_tok);
		num_ports++;
    }

    int nbytes = snprintf(NULL,0,"%s:NUM_SERVICES",component_name);
    char ns_buff[nbytes+1];
    snprintf(ns_buff,nbytes+1,"%s:NUM_SERVICES",component_name);
    arc_model_assign_property_int(a_m,ns_buff,num_ports);

    nbytes = snprintf(NULL,0,"%s:NUM_VULNERABILITIES",component_name);
    char nv_buff[nbytes+1];
    snprintf(nv_buff,nbytes+1,"%s:NUM_VULNERABILITIES",component_name);
    arc_model_assign_property_int(a_m,nv_buff,0);

    nbytes = snprintf(NULL,0,"%s:NUM_CONNECTIONS",component_name);
    char nc_buff[nbytes+1];
    snprintf(nc_buff,nbytes+1,"%s:NUM_CONNECTIONS",component_name);
    arc_model_assign_property_int(a_m,nc_buff,1);

    nbytes = snprintf(NULL,0,"%s:EXPLOITATION_STATE",component_name);
    char es_buff[nbytes+1];
    snprintf(es_buff,nbytes+1,"%s:EXPLOITATION_STATE",component_name);
    arc_model_assign_property_str(a_m,es_buff,"None");
    tokenizer_cleanup(&commaspace_tok);
}


static char *next_port_info_chunk(char *str, char until_c)
{
    char *walk_str = str;
    char *chunk = NULL;
    size_t num_chars = 0;
    while(*walk_str!='\0' && *walk_str!=until_c)
    {
		num_chars++;
		walk_str++;
    }

    if(num_chars > 0)
    {
		chunk = strndup(str,num_chars);
	
    }
    return chunk;
}


static char *qualified_iface_property(char *component, char *interface, char *property)
{
    char *qual_name = NULL;
    size_t num_bytes = snprintf(NULL,0,"%s:%s:%s",component,interface,property);
    if(num_bytes > 3)
    {
		qual_name = malloc(num_bytes+1);
		snprintf(qual_name,num_bytes+1,"%s:%s:%s",component,interface,property);
    }

    return qual_name;
}

static void parse_nmap_port_field(char *port_field, struct arc_model *a_m, char *component_name)
{

    char *interface = NULL;
    char *port = next_port_info_chunk(port_field,'/');
    if(port)
    {
		interface = make_identifier(port, 'I');
		arc_model_add_interface(a_m, component_name, interface);
		char *qual_name = qualified_iface_property(component_name, interface, "Port");
		arc_model_assign_property_str(a_m, qual_name, port);
		port_field+=strlen(port);
	
		free(qual_name);
		free(port);
	
    }
    port_field++;
    char *state = next_port_info_chunk(port_field,'/');
    if(state)
    {
		char *qual_name = qualified_iface_property(component_name, interface, "State");
		arc_model_assign_property_str(a_m, qual_name, state);
		port_field+=strlen(state);
	
		free(qual_name);
		free(state);
    }
    port_field++;
    char *protocol = next_port_info_chunk(port_field,'/');
    if(protocol)
    {
		char *qual_name = qualified_iface_property(component_name, interface, "Protocol");
		arc_model_assign_property_str(a_m, qual_name, protocol);
		port_field+=strlen(protocol);
	
		free(qual_name);
		free(protocol);
    }
    port_field++;
    char *owner = next_port_info_chunk(port_field,'/');
    if(owner)
    {

		char *qual_name = qualified_iface_property(component_name, interface, "Owner");
		arc_model_assign_property_str(a_m, qual_name, owner);
		port_field+=strlen(owner);
	
		free(qual_name);
		free(owner);
    }
    port_field++;
    char *service = next_port_info_chunk(port_field,'/');
    if(service)
    {
		char *qual_name = qualified_iface_property(component_name, interface, "Service");
		arc_model_assign_property_str(a_m, qual_name, service);
		port_field+=strlen(service);
		free(qual_name);
		free(service);
    }
    port_field++;
    char *sun_rpc_info = next_port_info_chunk(port_field,'/');
    if(sun_rpc_info)
    {
		port_field+=strlen(sun_rpc_info);
		free(sun_rpc_info);
    }
    port_field++;
    char *version_info = next_port_info_chunk(port_field,'/');
    if(version_info)
    {
		char *qual_name = qualified_iface_property(component_name, interface, "Version");
		arc_model_assign_property_str(a_m, qual_name, version_info);
		port_field+=strlen(version_info);
	
		free(qual_name);
		free(version_info);
    }

    if(interface)
    {
		free(interface);
    }
}

bool net_scan_guard(struct arc_model *a_m, char *args)
{
    bool res = true;
    struct arc_value target_ipr = arc_model_get_property(a_m,"IPR");
    if(target_ipr.type != V_STRING)
    {
		fprintf(stderr,"[nmap] String Property:IPR is required to peform a NetWorkScan\n");
		res = false;
    }

    free(target_ipr.v_str);
    return res;
}

bool net_scan(struct arc_model *a_m, char *args)
{
    /* nmap TargetIPRange -oG - */

    bool res = true;
    struct arc_value target_ipr = arc_model_get_property(a_m,"IPR");
    if(target_ipr.type != V_STRING)
    {
		fprintf(stderr,"[nmap] String Property:IPR is required to peform a NetWorkScan\n");
		res = false;
    }
    else
    {
		

		
		struct tool_runner tool_runner;
		tool_runner_init(&tool_runner, "nmap", 4);
		
		tool_runner_add_arg(&tool_runner,target_ipr.v_str);
		tool_runner_add_arg(&tool_runner,"-A");
		tool_runner_add_arg(&tool_runner,"-oG");
		tool_runner_add_arg(&tool_runner,"-");
		
		tool_runner_run(&tool_runner);
		//tool_runner_print_summary(&tool_runner);;
		char *output = tool_runner.output;
		size_t num_skip = 0;
		char *line = next_line(output, &num_skip);
		output+=num_skip;
		while(line && num_skip > 0)
		{
	    
			if(line[0]!='#')
			{
				parse_nmap_grepable(line, a_m);
			}
	    
			num_skip = 0;
			line = next_line(output, &num_skip);
			output+=num_skip;
		}
		tool_runner_destroy(&tool_runner);
		free(target_ipr.v_str);
    }
	

    
    return res;
}