Commit message: Fix potential unsigned integer underflow
CVE: CVE-2019-14459
CWE: CWE-190
Vulnerability description: nfdump 1.6.17 and earlier is affected by an integer overflow in the function Process_ipfix_template_withdraw in ipfix.c that can be abused in order to crash the process remotely (denial of service).

Project: nfdump

static exporter_ipfix_domain_t *GetExporter(FlowSource_t *fs, ipfix_header_t *ipfix_header) {
#define IP_STRING_LEN   40
char ipstr[IP_STRING_LEN];
exporter_ipfix_domain_t **e = (exporter_ipfix_domain_t **)&(fs->exporter_data);
uint32_t ObservationDomain = ntohl(ipfix_header->ObservationDomain);

	while ( *e ) {
		if ( (*e)->info.id == ObservationDomain && (*e)->info.version == 10 && 
			 (*e)->info.ip.V6[0] == fs->ip.V6[0] && (*e)->info.ip.V6[1] == fs->ip.V6[1]) 
			return *e;
		e = &((*e)->next);
	}

	if ( fs->sa_family == AF_INET ) {
		uint32_t _ip = htonl(fs->ip.V4);
		inet_ntop(AF_INET, &_ip, ipstr, sizeof(ipstr));
	} else if ( fs->sa_family == AF_INET6 ) {
		uint64_t _ip[2];
		_ip[0] = htonll(fs->ip.V6[0]);
		_ip[1] = htonll(fs->ip.V6[1]);
		inet_ntop(AF_INET6, &_ip, ipstr, sizeof(ipstr));
	} else {
		strncpy(ipstr, "<unknown>", IP_STRING_LEN);
	}

	*e = (exporter_ipfix_domain_t *)malloc(sizeof(exporter_ipfix_domain_t));
	if ( !(*e)) {
		LogError("Process_ipfix: Panic! malloc() %s line %d: %s", __FILE__, __LINE__, strerror (errno));
		return NULL;
	}
	memset((void *)(*e), 0, sizeof(exporter_ipfix_domain_t));
	(*e)->info.header.type  = ExporterInfoRecordType;
	(*e)->info.header.size  = sizeof(exporter_info_record_t);
	(*e)->info.id 			= ObservationDomain;
	(*e)->info.ip			= fs->ip;
	(*e)->info.sa_family	= fs->sa_family;
	(*e)->info.version 		= 10;
	(*e)->info.sysid	 	= 0;

	(*e)->TemplateRecords 	= 0;
	(*e)->DataRecords 	 	= 0;
	(*e)->sequence_failure 	= 0;
	(*e)->padding_errors 	= 0;
	(*e)->next	 			= NULL;
	(*e)->sampler 			= NULL;

	FlushInfoExporter(fs, &((*e)->info));

	dbg_printf("[%u] New exporter: SysID: %u, Observation domain %u from: %s\n", 
		ObservationDomain, (*e)->info.sysid, ObservationDomain, ipstr);
	LogInfo("Process_ipfix: New exporter: SysID: %u, Observation domain %u from: %s\n", 
		(*e)->info.sysid, ObservationDomain, ipstr);


	return (*e);

} // End of GetExporter

Project: nfdump
File: ipfix.c

static input_translation_t *GetTranslationTable(exporter_ipfix_domain_t *exporter, uint16_t id) {
input_translation_t *table;

	if ( exporter->current_table && ( exporter->current_table->id == id ) )
		return exporter->current_table;

	table = exporter->input_translation_table;
	while ( table ) {
		if ( table->id == id ) {
			exporter->current_table = table;
			return table;
		}

		table = table->next;
	}

	dbg_printf("[%u] Get translation table %u: %s\n", exporter->info.id, id, table == NULL ? "not found" : "found");

	exporter->current_table = table;
	return table;

} // End of GetTranslationTable

Project: nfdump
File: ipfix.c

static uint32_t MapElement(uint16_t Type, uint16_t Length, uint32_t order) {
int	index;

	cache.input_order[order].type	= Type;
	cache.input_order[order].length	= Length;

	index = cache.lookup_info[Type].index;
	if ( index ) {
		while ( index && ipfix_element_map[index].id == Type ) {
			if ( Length == ipfix_element_map[index].length ) {
				cache.lookup_info[Type].found  = 1;
				cache.lookup_info[Type].length = Length;
				cache.lookup_info[Type].index  = index;
				dbg_printf("found extension %u for type: %u, input length: %u output length: %u Extension: %u\n", 
					ipfix_element_map[index].extension, ipfix_element_map[index].id, 
					ipfix_element_map[index].length, ipfix_element_map[index].out_length, ipfix_element_map[index].extension);
				return ipfix_element_map[index].extension;
			}
			index++;
		}
		dbg_printf("Skip known element type: %u, Unknown length: %u\n", Type, Length);
	} else {
		dbg_printf("Skip unknown element type: %u, Length: %u\n", Type, Length);
	}

	cache.input_order[order].type = SKIP_ELEMENT;
	return 0;

} // End of MapElement