From: Kevin Day Date: Thu, 7 Jun 2012 23:06:57 +0000 (-0500) Subject: Update: rewrite firewall, adding support for custom chains X-Git-Tag: 0.3.0~18 X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=229be686eca84f3ee1e8e9acd39cfe79a43e85e0;p=fll Update: rewrite firewall, adding support for custom chains This is a major redesign of the firewall program. Iptables chains are now supported automatically. Each new basic list is itself a chain. Reserved words not allowed for custom chains are: - main - stop - lock The 'main' chain signifies use of the default iptables chain. The layout and structure of the files have been rewritten to utilize chains. The default-firewall file has been removed and replaced with the following files: - firewall-first - firewall-last - firewall-other The newly written rules defines default firewall rules and chains such that there the following self-explanatory chains: - input-tcp - input-udp - input-icmp - output-tcp - output-udp - output-firewall In addition to the above changes, the base functionality has been broken up into smaller functions to improve code quality. --- diff --git a/level_3/firewall/c/firewall.c b/level_3/firewall/c/firewall.c index c4924d4..ebb9a63 100644 --- a/level_3/firewall/c/firewall.c +++ b/level_3/firewall/c/firewall.c @@ -108,21 +108,21 @@ extern "C"{ #ifndef _di_firewall_main_ f_return_status firewall_main(const f_s_int argc, const f_string argv[], firewall_data *data) { - f_status status = f_status_initialize; - f_status allocation_status = f_status_initialize; + f_status status = f_status_initialize; + f_status status2 = f_status_initialize; status = fl_process_parameters(argc, argv, data->parameters, firewall_total_parameters, &data->remaining); // load colors when not told to show no colors if (data->parameters[firewall_parameter_no_color].result == f_console_result_none) { - fll_new_color_context(allocation_status, data->context); + fll_new_color_context(status2, data->context); - if (allocation_status == f_none) { + if (status2 == f_none) { fll_colors_load_context(&data->context, data->parameters[firewall_parameter_light].result == f_console_result_found); } else { fprintf(f_standard_error, "Critical Error: unable to allocate memory\n"); firewall_delete_data(data); - return allocation_status; + return status2; } } @@ -204,82 +204,9 @@ extern "C"{ } if (found_command) { - // load the global file - { - f_file file = f_file_initialize; - - status = f_file_open(&file, (f_string) network_path firewall_file_default); - - if (status != f_none) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } else if (status == f_file_not_found) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'", network_path firewall_file_default); - } else if (status == f_file_open_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", network_path firewall_file_default); - } else if (status == f_file_descriptor_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", network_path firewall_file_default); - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", status); - } - - firewall_delete_data(data); - return status; - } - - // TODO: this file size set functionality might be turned into an fl_file (or f_file) function - if (data->file_position.total_elements == 0) { - fseek(file.file, 0, SEEK_END); - data->file_position.total_elements = ftell(file.file); - fseek(file.file, 0, SEEK_SET); - } - - status = fl_file_read(file, data->file_position, &data->buffer); - - f_file_close(&file); - - if (status != f_none && status != f_none_on_eof) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } else if (status == f_overflow) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", network_path firewall_file_default); - } else if (status == f_file_not_open) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", network_path firewall_file_default); - } else if (status == f_file_seek_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", network_path firewall_file_default); - } else if (status == f_file_read_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", network_path firewall_file_default); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", status); - } - - firewall_delete_data(data); - return status; - } else { - f_string_location input = f_string_location_initialize; - - input.stop = data->buffer.used - 1; - - status = fll_fss_basic_list_read(&data->buffer, &input, &data->objects, &data->contents); - } - - if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_list_read() for the file '%s'", network_path firewall_file_default); - } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", network_path firewall_file_default); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'", status, network_path firewall_file_default); - } - - firewall_delete_data(data); - return status; - } - } + firewall_local_data local = firewall_local_data_initialize; + firewall_reserved_chains reserved = firewall_reserved_chains_initialize; + f_string_location input = f_string_location_initialize; if (command == firewall_parameter_command_show) { // Warning: these are hardcoded print commands (I am not certain how I am going to implement external 'show' rules as the default-firewall setting file is the wrong place to put this) @@ -318,6 +245,7 @@ extern "C"{ if (f_macro_test_for_allocation_errors(status)) { fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); + firewall_delete_local_data(&local); firewall_delete_data(data); return status; } @@ -440,8 +368,9 @@ extern "C"{ arguments.array[4].used = 0; arguments.array[5].used = 0; arguments.array[6].used = 0; - f_delete_dynamic_strings(status, arguments); + f_delete_dynamic_strings(status, arguments); + firewall_delete_local_data(&local); firewall_delete_data(data); return f_none; } @@ -451,30 +380,33 @@ extern "C"{ if (f_macro_test_for_allocation_errors(status)) { fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); + firewall_delete_local_data(&local); firewall_delete_data(data); return status; } else if (status == f_no_data) { fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: could not find any network devices"); + firewall_delete_local_data(&local); firewall_delete_data(data); return status; } else if (status == f_failure) { fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: failed to read the device directory '%s'", network_devices); + firewall_delete_local_data(&local); firewall_delete_data(data); return status; } // remove "lo" (loopback) from the device listing { - f_string_length counter = f_string_length_initialize; + f_string_length i = f_string_length_initialize; - for (; counter < data->devices.used; counter++) { - if (fl_compare_strings((f_string) "lo", data->devices.array[counter].string, 3, data->devices.array[counter].used) == f_equal_to) { - f_dynamic_string swap_string = data->devices.array[counter]; + for (; i < data->devices.used; i++) { + if (fl_compare_strings((f_string) firewall_device_loop, data->devices.array[i].string, firewall_device_loop_length + 1, data->devices.array[i].used) == f_equal_to) { + f_dynamic_string swap_string = data->devices.array[i]; data->devices.used--; - for (; counter < data->devices.used; counter++) { - data->devices.array[counter] = data->devices.array[counter+1]; + for (; i < data->devices.used; i++) { + data->devices.array[i] = data->devices.array[i+1]; } data->devices.array[data->devices.used] = swap_string; @@ -482,947 +414,252 @@ extern "C"{ } } - // if at least one specific device was specified, then only use the specified devices, otherwise use all - if (data->remaining.used > 0) { - f_string_length device = f_string_length_initialize; - f_string_length counter = f_string_length_initialize; - f_string_length total = f_string_length_initialize; - f_string_length i = f_string_length_initialize; - f_bool matched = f_false; + if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart || command == firewall_parameter_command_lock) { + status = firewall_buffer_rules(network_path firewall_file_other, f_false, &local, data); - for (total = data->devices.used; device < total; device++) { - matched = f_false; + if (status != f_none && status != f_none_on_eof && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } + + { + f_array_length i = f_array_length_initialize; + f_string_length length = f_string_length_initialize; + + for (; i < local.chain_objects.used; i++) { + length = local.chain_objects.array[i].stop - local.chain_objects.array[i].start + 1; - for (counter = 0; counter < data->remaining.used; counter++) { - if (strncmp(data->devices.array[device].string, argv[data->remaining.array[counter]], strlen(argv[data->remaining.array[counter]])) == 0) { - matched = f_true; + if (!reserved.has_stop && fl_compare_strings((f_string) firewall_group_stop, local.buffer.string + local.chain_objects.array[i].start, firewall_group_stop_length, length) == f_equal_to) { + reserved.stop_at = i; + reserved.has_stop = f_true; + } else if (!reserved.has_lock && fl_compare_strings((f_string) firewall_group_lock, local.buffer.string + local.chain_objects.array[i].start, firewall_group_lock_length, length) == f_equal_to) { + reserved.lock_at = i; + reserved.has_lock = f_true; } - } + } // for + } - if (!matched) { - f_dynamic_string swap_string = data->devices.array[device]; + if (command == firewall_parameter_command_lock) { + if (reserved.has_lock) { + local.is_main = f_false; + local.is_stop = f_false; + local.is_lock = f_true; + local.chain = reserved.lock_at; - data->devices.used--; + input.start = local.chain_contents.array[reserved.lock_at].array[0].start; + input.stop = local.chain_contents.array[reserved.lock_at].array[0].stop; - for (i = device; i < data->devices.used; i++) { - data->devices.array[i] = data->devices.array[i+1]; - } + status = firewall_process_rules(&input, &local, data); - data->devices.array[data->devices.used] = swap_string; + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform lock request because the lock instructions are missing from: %s.", network_path firewall_file_other); - total--; - device--; + firewall_delete_local_data(&local); + firewall_delete_data(data); + return f_invalid_data; } } - } - // report and remove all "invalid" devices that are specified in the "remaining" variable - { - f_string_length device = f_string_length_initialize; - f_string_length counter = f_string_length_initialize; - f_bool matched = f_false; + if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart) { + if (reserved.has_stop) { + local.is_global = f_true; + local.is_main = f_false; + local.is_stop = f_true; + local.is_lock = f_false; + local.chain = reserved.stop_at; + + input.start = local.chain_contents.array[reserved.stop_at].array[0].start; + input.stop = local.chain_contents.array[reserved.stop_at].array[0].stop; - for (; counter < data->remaining.used; counter++) { - matched = f_false; + status = firewall_process_rules(&input, &local, data); - for (device = 0; device < data->devices.used; device++) { - if (strncmp(data->devices.array[device].string, argv[data->remaining.array[counter]], strlen(argv[data->remaining.array[counter]])) == 0) { - matched = f_true; + if (status != f_none || command == firewall_parameter_command_stop) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; } - } + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform stop request because the lock instructions are missing from: %s.", network_path firewall_file_other); - if (!matched) { - fl_print_color_line(f_standard_warning, data->context.warning, data->context.reset, "WARNING: There is no device by the name of '%s'", argv[data->remaining.array[counter]]); + firewall_delete_local_data(&local); + firewall_delete_data(data); + return f_invalid_data; } } - // cleanup, the 'remaining' parameters are no longer needed - f_delete_string_locations(status, data->remaining); + firewall_delete_local_data(&local); } - // identify global firewall settings - f_string_length first = f_string_length_initialize; - f_string_length last = f_string_length_initialize; - f_string_length stop = f_string_length_initialize; - f_string_length lock = f_string_length_initialize; - - f_bool found_first = f_false; - f_bool found_last = f_false; - f_bool found_stop = f_false; - f_bool found_lock = f_false; - - f_string_length length = f_string_length_initialize; - f_string_length counter = f_string_length_initialize; - - // identify which position is which - for (; counter < data->objects.used; counter++) { - length = data->objects.array[counter].stop - data->objects.array[counter].start + 1; - - if (!found_first && fl_compare_strings((f_string) firewall_group_first, data->buffer.string + data->objects.array[counter].start, firewall_group_first_length, length) == f_equal_to) { - first = counter; - found_first = f_true; - } else if (!found_last && fl_compare_strings((f_string) firewall_group_last, data->buffer.string + data->objects.array[counter].start, firewall_group_last_length, length) == f_equal_to) { - last = counter; - found_last = f_true; - } else if (!found_stop && fl_compare_strings((f_string) firewall_group_stop, data->buffer.string + data->objects.array[counter].start, firewall_group_stop_length, length) == f_equal_to) { - stop = counter; - found_stop = f_true; - } else if (!found_lock && fl_compare_strings((f_string) firewall_group_lock, data->buffer.string + data->objects.array[counter].start, firewall_group_lock_length, length) == f_equal_to) { - lock = counter; - found_lock = f_true; - } else { - if (data->custom.used >= data->custom.size) { - f_resize_string_lengths(status, data->custom, data->custom.size + firewall_default_allocation_step); + if (command == firewall_parameter_command_start || command == firewall_parameter_command_restart) { + status = firewall_buffer_rules(network_path firewall_file_first, f_false, &local, data); - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory"); - firewall_delete_data(data); - return status; - } - } + if (status != f_none && status != f_none_on_eof && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + }; - data->custom.array[data->custom.used] = counter; - data->custom.used++; + status = firewall_create_custom_chains(&reserved, &local, data); + + if (status != f_none) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; } - } - if (found_first && found_last && found_stop && found_lock) { - f_string_length error_file = f_string_length_initialize; - status = f_none; + f_array_length i = 0; - f_fss_objects extended_objects = f_fss_objects_initialize; - f_fss_contents extended_contents = f_fss_contents_initialize; + local.is_global = f_true; + local.is_stop = f_false; + local.is_lock = f_false; - if (command == firewall_parameter_command_lock) { - f_string_location input = f_string_location_initialize; + while (i < local.chain_contents.used) { + input.start = local.chain_contents.array[i].array[0].start; + input.stop = local.chain_contents.array[i].array[0].stop; - input.start = data->contents.array[lock].array[0].start; - input.stop = data->contents.array[lock].array[0].stop; - error_file = lock; + local.is_main = reserved.has_main && i == reserved.main_at ? f_true : f_false; + local.chain = i; - status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents); + status = firewall_process_rules(&input, &local, data); - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data, f_null); + if ((status != f_none && status != f_no_data && status != f_no_data_on_stop) || command == firewall_parameter_command_stop) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } + i++; + } // while + + firewall_delete_local_data(&local); + + for (i = 0; i < data->devices.used; i++) { + local.device = i; - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); + { + f_dynamic_string file_path = f_dynamic_string_initialize; + f_resize_dynamic_string(status, file_path, network_path_length + data->devices.array[i].used + firewall_file_suffix_length + 1); + + if (f_macro_test_for_allocation_errors(status)) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory.", status); + firewall_delete_local_data(&local); firewall_delete_data(data); return status; } - } - } else { - if (command == firewall_parameter_command_stop || command == firewall_parameter_command_restart) { - f_string_location input = f_string_location_initialize; - input.start = data->contents.array[stop].array[0].start; - input.stop = data->contents.array[stop].array[0].stop; - error_file = stop; + strncat(file_path.string, network_path, network_path_length); + strncat(file_path.string + network_path_length, data->devices.array[i].string, data->devices.array[i].used); + strncat(file_path.string, firewall_file_suffix, firewall_file_suffix_length); + file_path.used = file_path.size; + file_path.string[file_path.used] = 0; - status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents); + status = firewall_buffer_rules(file_path.string, f_true, &local, data); - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data, f_null); - } + f_delete_dynamic_string(status2, file_path); } - if ((status == f_none || status == f_none_on_stop || status == f_none_on_eos) && (command == firewall_parameter_command_start || command == firewall_parameter_command_restart)) { - f_delete_fss_objects(status, extended_objects); - f_delete_fss_contents(status, extended_contents); - - f_string_location input = f_string_location_initialize; + if (status != f_none && status != f_none_on_eof && status != f_none_on_eos && status != f_none_on_stop) { + firewall_delete_local_data(&local); - input.start = data->contents.array[first].array[0].start; - input.stop = data->contents.array[first].array[0].stop; - error_file = first; + if (status == f_file_not_found || status == f_file_open_error || status == f_file_descriptor_error || status == fl_fss_found_object_no_content) { + continue; + } - status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents); + firewall_delete_data(data); + return status; + } - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data, f_null); + status = firewall_create_custom_chains(&reserved, &local, data); - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } + if (status != f_none) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); + f_array_length j = 0; - firewall_delete_data(data); - return status; - } else { - f_delete_fss_objects(status, extended_objects); - f_delete_fss_contents(status, extended_contents); - - f_string_length counter = 0; - - { - f_dynamic_string chain_argument = f_dynamic_string_initialize; - - while (counter < data->custom.used) { - f_dynamic_string custom_chain = f_dynamic_string_initialize; - f_string_length chain_location = 0; - - input.start = data->objects.array[data->custom.array[counter]].start; - input.stop = data->objects.array[data->custom.array[counter]].stop; + local.is_global = f_false; + local.is_stop = f_false; + local.is_lock = f_false; - // ensure that the chain exists - if (counter < data->custom.used && data->custom.array[counter] < data->objects.used) { - f_string_length counter2 = 0; - f_string_length max_size = 0; - f_bool new_chain = f_true; - - counter2 = input.start; - max_size = input.stop - input.start + 1; - - if (max_size >= custom_chain.size) { - f_resize_dynamic_string(status, custom_chain, max_size + firewall_default_allocation_step); + for (; j < local.chain_contents.used; j++) { + input.start = local.chain_contents.array[j].array[0].start; + input.stop = local.chain_contents.array[j].array[0].stop; - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - } - - custom_chain.used = 0; - counter2 = input.start; - while (counter2 <= input.stop && custom_chain.used <= custom_chain.size) { - if (data->buffer.string[counter2] == f_fss_delimit_placeholder) { - counter2++; - continue; - } + local.is_main = reserved.has_main && j == reserved.main_at ? f_true : f_false; + local.chain = j; - custom_chain.string[custom_chain.used] = data->buffer.string[counter2]; - custom_chain.used++; - counter2++; - } // while + status = firewall_process_rules(&input, &local, data); - if (firewall_chain_create_command_length > chain_argument.size) { - f_resize_dynamic_string(status, chain_argument, firewall_chain_create_command_length); + if ((status != f_none && status != f_no_data && status != f_no_data_on_stop) || command == firewall_parameter_command_stop) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } + } // for - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; + firewall_delete_local_data(&local); + } // for - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - } + // TODO: process each network device here. + // process the "main" rule. + // process all remaining rules in top-down order, skipping the main rule. + // pre-process the "network device" file, storing main location as well as creating&storing each of the custom chains. + // process the "main" rule. + // process all remaining rules in top-down order, skipping the main rule. + // pre-process the "last" file, storing main location as well as creating&storing each of the custom chains. + // process the "main" rule. + // process all remaining rules in top-down order, skipping the main rule. - strncat(chain_argument.string, firewall_chain_create_command, firewall_chain_create_command_length); - chain_argument.used = firewall_chain_create_command_length; - chain_location = 0; - - - while (chain_location < data->chains.used) { - if (fl_compare_dynamic_strings(custom_chain, data->chains.array[chain_location]) == f_equal_to) { - f_delete_dynamic_string(allocation_status, custom_chain); - - new_chain = f_false; - break; - } - - chain_location++; - } // while + status = firewall_buffer_rules(network_path firewall_file_last, f_false, &local, data); - if (new_chain) { - if (data->chains.used >= data->chains.size) { - f_resize_dynamic_strings(status, data->chains, data->chains.size + firewall_default_allocation_step); - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - } - - f_s_int results = 0; - f_dynamic_strings arguments = f_dynamic_strings_initialize; - - f_resize_dynamic_strings(status, arguments, 3); - - arguments.array[0].string = (f_string) firewall_chain_create_command; - arguments.array[1].string = chain_argument.string; - arguments.array[2].string = custom_chain.string; - - arguments.array[0].used = firewall_chain_create_command_length; - arguments.array[1].used = chain_argument.used; - arguments.array[2].used = custom_chain.used; - - arguments.used = 3; - arguments.size = 3; - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - - status = fll_execute_program((f_string) firewall_program_name, arguments, &results); - - if (status == f_failure) { - f_status allocation_status = f_status_initialize; - - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name); - fprintf(f_standard_error, " "); - - f_string_length i = f_string_length_initialize; - - fl_print_color_code(f_standard_error, data->context.error); - - for (; i < arguments.used; i++) { - fprintf(f_standard_error, "%s ", arguments.array[i].string); - } - - fl_print_color_code(f_standard_error, data->context.reset); - fprintf(f_standard_error, "\n"); - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } else if (status == f_invalid_parameter) { - f_status allocation_status = f_status_initialize; - - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_execute_path()"); - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_strings(status, arguments); - - data->chains.array[data->chains.used] = custom_chain; - custom_chain.string = 0; - custom_chain.used = 0; - chain_location = data->chains.used; - data->chains.used++; - } - } - - input.start = data->contents.array[data->custom.array[counter]].array[0].start; - input.stop = data->contents.array[data->custom.array[counter]].array[0].stop; - - status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents); - - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_true, counter, data->buffer, *data, &data->chains.array[chain_location]); - - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } - } - } - - f_delete_dynamic_string(status, chain_argument); - f_delete_fss_objects(status, extended_objects); - f_delete_fss_contents(status, extended_contents); - - counter++; - } // while - } + if (status != f_none && status != f_none_on_eof && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; + } - counter = 0; - - for (; counter < data->devices.used; counter++) { - f_file file = f_file_initialize; - f_dynamic_string file_path = f_dynamic_string_initialize; - f_dynamic_string buffer = f_dynamic_string_initialize; - f_file_position file_position = f_file_position_initialize; - - f_fss_objects list_objects = f_fss_objects_initialize; - f_fss_contents list_contents = f_fss_objects_initialize; - - f_resize_dynamic_string(status, file_path, network_path_length + data->devices.array[counter].used + firewall_file_suffix_length + 1); - - if (status == f_none) { - strncat(file_path.string, network_path, network_path_length); - strncat(file_path.string + network_path_length, data->devices.array[counter].string, data->devices.array[counter].used); - strncat(file_path.string, firewall_file_suffix, firewall_file_suffix_length); - file_path.used = file_path.size; - file_path.string[file_path.used] = 0; - - status = f_file_open(&file, file_path.string); - } - - if (status != f_none) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()"); - } else if (status == f_file_not_found) { - // If these files do not exist, it is not a problem (they are not required) - } else if (status == f_file_open_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'", file_path.string); - } else if (status == f_file_descriptor_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'", file_path.string); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - - f_file_close(&file); - f_delete_dynamic_string(allocation_status, file_path); - firewall_delete_data(data); - return status; - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open()", status); - } - - f_file_close(&file); - f_delete_dynamic_string(allocation_status, file_path); - continue; - } - - - if (data->file_position.total_elements == 0) { - fseek(file.file, 0, SEEK_END); - data->file_position.total_elements = ftell(file.file); - fseek(file.file, 0, SEEK_SET); - } - - status = fl_file_read(file, file_position, &buffer); - - f_file_close(&file); - - if (status != f_none && status != f_none_on_eof) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()"); - } else if (status == f_overflow) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'", file_path.string); - } else if (status == f_file_not_open) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open", file_path.string); - } else if (status == f_file_seek_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'", file_path.string); - } else if (status == f_file_read_error) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'", file_path.string); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - firewall_delete_data(data); - return status; - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read()", status); - } - - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - continue; - } - - { - f_string_location input = f_string_location_initialize; - - input.stop = buffer.used - 1; - - status = fll_fss_basic_list_read(&buffer, &input, &list_objects, &list_contents); - } - - if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_list_read() for the file '%s'", file_path.string); - } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", file_path.string); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'", status, file_path.string); - } - - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - - { - f_string_length buffer_counter = f_string_length_initialize; - f_string_length length = f_string_length_initialize; - - while (buffer_counter < list_objects.used) { - length = list_objects.array[buffer_counter].stop - list_objects.array[buffer_counter].start + 1; - - if (fl_compare_strings((f_string) firewall_group_main, buffer.string + list_objects.array[buffer_counter].start, firewall_group_main_length, length) == f_equal_to) { - f_string_location input = f_string_location_initialize; - - input.start = list_contents.array[buffer_counter].array[0].start; - input.stop = list_contents.array[buffer_counter].array[0].stop; - - status = fll_fss_extended_read(&buffer, &input, &extended_objects, &extended_contents); - - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_false, counter, buffer, *data, f_null); - - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } - } - } else { - if (status == f_invalid_parameter) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_extended_read() for the file '%s'", file_path.string); - } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'", file_path.string); - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_extended_read() for the file '%s'", status, file_path.string); - } - } - } else if (fl_compare_strings((f_string) firewall_group_first, buffer.string + list_objects.array[buffer_counter].start, firewall_group_first_length, length) == f_equal_to) { - // skip this, device-specific rules do not support this. - } else if (fl_compare_strings((f_string) firewall_group_last, buffer.string + list_objects.array[buffer_counter].start, firewall_group_last_length, length) == f_equal_to) { - // skip this, device-specific rules do not support this. - } else if (fl_compare_strings((f_string) firewall_group_stop, buffer.string + list_objects.array[buffer_counter].start, firewall_group_stop_length, length) == f_equal_to) { - // skip this, device-specific rules do not support this. - } else if (fl_compare_strings((f_string) firewall_group_lock, buffer.string + list_objects.array[buffer_counter].start, firewall_group_lock_length, length) == f_equal_to) { - // skip this, device-specific rules do not support this. - } else { - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - - f_string_location input = f_string_location_initialize; - - f_dynamic_string custom_chain = f_dynamic_string_initialize; - f_dynamic_string chain_argument = f_dynamic_string_initialize; - f_string_length chain_location = 0; - - f_string_length counter2 = 0; - f_string_length max_size = 0; - f_bool new_chain = f_true; - - input.start = list_objects.array[buffer_counter].start; - input.stop = list_objects.array[buffer_counter].stop; - - if (data->chains.used >= data->chains.size) { - f_resize_dynamic_strings(status, data->chains, data->chains.size + firewall_default_allocation_step); - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - firewall_delete_data(data); - return status; - } - } - - // ensure that the chain exists - counter2 = list_objects.array[buffer_counter].start; - max_size = list_objects.array[buffer_counter].stop - list_objects.array[buffer_counter].start + 1; - - if (max_size >= custom_chain.size) { - f_resize_dynamic_string(status, custom_chain, max_size + firewall_default_allocation_step); - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - } - - custom_chain.used = 0; - counter2 = input.start; - while (counter2 <= input.stop && custom_chain.used <= custom_chain.size) { - if (buffer.string[counter2] == f_fss_delimit_placeholder) { - counter2++; - continue; - } - - custom_chain.string[custom_chain.used] = buffer.string[counter2]; - custom_chain.used++; - counter2++; - } // while - - if (firewall_chain_create_command_length > chain_argument.size) { - f_resize_dynamic_string(status, chain_argument, firewall_chain_create_command_length); - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - } - - strncat(chain_argument.string, firewall_chain_create_command, firewall_chain_create_command_length); - chain_argument.used = firewall_chain_create_command_length; - chain_location = 0; - - while (chain_location < data->chains.used) { - if (fl_compare_dynamic_strings(custom_chain, data->chains.array[chain_location]) == f_equal_to) { - f_delete_dynamic_string(allocation_status, custom_chain); - - new_chain = f_false; - break; - } - - chain_location++; - } // while - - if (new_chain) { - if (data->chains.used >= data->chains.size) { - f_resize_dynamic_strings(status, data->chains, data->chains.size + firewall_default_allocation_step); - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - } - - f_s_int results = 0; - f_dynamic_strings arguments = f_dynamic_strings_initialize; - - f_resize_dynamic_strings(status, arguments, 3); - - arguments.array[0].string = (f_string) firewall_chain_create_command; - arguments.array[1].string = chain_argument.string; - arguments.array[2].string = custom_chain.string; - - arguments.array[0].used = firewall_chain_create_command_length; - arguments.array[1].used = chain_argument.used; - arguments.array[2].used = custom_chain.used; - - arguments.used = 3; - arguments.size = 3; - - if (f_macro_test_for_allocation_errors(status)) { - f_status allocation_status = f_status_initialize; - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - - status = fll_execute_program((f_string) firewall_program_name, arguments, &results); - - if (status == f_failure) { - f_status allocation_status = f_status_initialize; - - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name); - fprintf(f_standard_error, " "); - - f_string_length i = f_string_length_initialize; - - fl_print_color_code(f_standard_error, data->context.error); - - for (; i < arguments.used; i++) { - fprintf(f_standard_error, "%s ", arguments.array[i].string); - } - - fl_print_color_code(f_standard_error, data->context.reset); - fprintf(f_standard_error, "\n"); - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } else if (status == f_invalid_parameter) { - f_status allocation_status = f_status_initialize; - - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_execute_path()"); - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_string(allocation_status, custom_chain); - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_dynamic_strings(allocation_status, arguments); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - firewall_delete_data(data); - return status; - } - - arguments.array[0].string = 0; - arguments.array[1].string = 0; - arguments.array[2].string = 0; - - arguments.array[0].used = 0; - arguments.array[1].used = 0; - arguments.array[2].used = 0; - - f_delete_dynamic_strings(status, arguments); - - data->chains.array[data->chains.used] = custom_chain; - custom_chain.string = 0; - custom_chain.used = 0; - chain_location = data->chains.used; - data->chains.used++; - } - - input.start = list_contents.array[buffer_counter].array[0].start; - input.stop = list_contents.array[buffer_counter].array[0].stop; - - status = fll_fss_extended_read(&buffer, &input, &extended_objects, &extended_contents); - - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_false, buffer_counter, buffer, *data, &data->chains.array[chain_location]); - - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } - } - } - - f_delete_dynamic_string(allocation_status, chain_argument); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - } - - buffer_counter++; - } // while - } - - f_delete_dynamic_string(allocation_status, buffer); - f_delete_dynamic_string(allocation_status, file_path); - f_delete_fss_objects(allocation_status, list_objects); - f_delete_fss_contents(allocation_status, list_contents); - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - } + status = firewall_create_custom_chains(&reserved, &local, data); - input.start = data->contents.array[last].array[0].start; - input.stop = data->contents.array[last].array[0].stop; - error_file = last; + if (status != f_none) { + firewall_macro_delete_fss_buffers(status2, local.buffer, local.chain_objects, local.chain_contents) + firewall_delete_data(data); + return status; + } - status = fll_fss_extended_read(&data->buffer, &input, &extended_objects, &extended_contents); + i = 0; - if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { - status = firewall_perform_commands(extended_objects, extended_contents, f_true, 0, data->buffer, *data, f_null); + local.is_global = f_true; + local.is_stop = f_false; + local.is_lock = f_false; - if (status != f_none) { - if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands()", status); - } + while (i < local.chain_contents.used) { + input.start = local.chain_contents.array[i].array[0].start; + input.stop = local.chain_contents.array[i].array[0].stop; - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); + local.is_main = reserved.has_main && i == reserved.main_at ? f_true : f_false; + local.chain = i; - firewall_delete_data(data); - return status; - } - } - } - } - } - } + status = firewall_process_rules(&input, &local, data); - if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { - if (status == f_invalid_parameter) { - fl_print_color_code(f_standard_error, data->context.error); - fprintf(f_standard_error, "INTERNAL ERROR: Invalid parameter when calling fll_fss_extended_read() for the file '"); - f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]); - fprintf(f_standard_error, "'"); - fl_print_color_code(f_standard_error, data->context.reset); - fprintf(f_standard_error, "\n"); - } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop) { - if (error_file == first || error_file == last || error_file == stop || error_file == lock) { - fl_print_color_code(f_standard_error, data->context.error); - fprintf(f_standard_error, "ERROR: No relevant data was found within the file '"); - f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]); - fprintf(f_standard_error, "'"); - fl_print_color_code(f_standard_error, data->context.reset); - fprintf(f_standard_error, "\n"); - } - } else if (f_macro_test_for_allocation_errors(status)) { - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory", status); - } else if (status == f_failure) { - // the error message has already been displayed - } else { - fl_print_color_code(f_standard_error, data->context.error); - fprintf(f_standard_error, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_extended_read() for the file '", status); - f_print_partial_dynamic_string(f_standard_error, data->buffer, data->contents.array[error_file].array[0]); - fprintf(f_standard_error, "'"); - fl_print_color_code(f_standard_error, data->context.reset); - fprintf(f_standard_error, "\n"); + if (status != f_none || command == firewall_parameter_command_stop) { + firewall_delete_local_data(&local); + firewall_delete_data(data); + return status; } - } - - f_delete_fss_objects(allocation_status, extended_objects); - f_delete_fss_contents(allocation_status, extended_contents); - } else { - const f_autochar *string = f_null; - - if (!found_first) { - string = firewall_group_first; - } else if (!found_last) { - string = firewall_group_last; - } else if (!found_stop) { - string = firewall_group_stop; - } else if (!found_lock) { - string = firewall_group_lock; - } - fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: The required basic list '%s' was not found inside of the file '%s'", string, network_path firewall_file_default); + i++; + } // while } // cleanup - f_delete_fss_contents(allocation_status, data->contents); - f_delete_fss_objects(allocation_status, data->objects); - f_delete_dynamic_string(allocation_status, data->buffer); + firewall_delete_local_data(&local); } else { fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: You did not pass a command"); status = f_invalid_parameter; @@ -1444,11 +681,7 @@ extern "C"{ i++; } // while - f_delete_fss_contents(status, data->contents); - f_delete_fss_objects(status, data->objects); - f_delete_string_lengths(status, data->custom); f_delete_dynamic_strings(status, data->chains); - f_delete_dynamic_string(status, data->buffer); f_delete_string_lengths(status, data->remaining); f_delete_dynamic_strings(status, data->devices); diff --git a/level_3/firewall/c/firewall.h b/level_3/firewall/c/firewall.h index 7bea9df..a8a6a44 100644 --- a/level_3/firewall/c/firewall.h +++ b/level_3/firewall/c/firewall.h @@ -18,6 +18,7 @@ // fll-0 includes #include +#include #include #include #include @@ -56,13 +57,17 @@ extern "C"{ #ifndef _di_firewall_paths_ #define network_path "/etc/network/" // TODO: this should be moved to a network project library, possibly the Paths project in fot the network project #define network_devices "/sys/class/net/" // TODO: this should also be moved to a network project library - #define firewall_file_default "default-firewall" + #define firewall_file_first "firewall-first" + #define firewall_file_last "firewall-last" + #define firewall_file_other "firewall-other" #define firewall_file_suffix "-firewall" #define firewall_program_name "iptables" #define network_path_length 13 #define network_devices_length 15 - #define firewall_file_default_length 16 + #define firewall_file_first_length 14 + #define firewall_file_last_length 13 + #define firewall_file_other_length 14 #define firewall_file_suffix_length 9 #define firewall_program_name_length 8 #endif // _di_firewall_paths_ @@ -72,14 +77,10 @@ extern "C"{ #endif // _di_firewall_default_allocation_step_ #ifndef _di_firewall_defines_ - #define firewall_group_first "first" - #define firewall_group_last "last" #define firewall_group_stop "stop" #define firewall_group_lock "lock" #define firewall_group_main "main" - #define firewall_group_first_length 5 - #define firewall_group_last_length 4 #define firewall_group_stop_length 4 #define firewall_group_lock_length 4 #define firewall_group_main_length 4 @@ -176,10 +177,12 @@ extern "C"{ #define firewall_device "device" #define firewall_device_all "all" #define firewall_device_this "this" + #define firewall_device_loop "lo" #define firewall_device_length 6 #define firewall_device_all_length 3 #define firewall_device_this_length 4 + #define firewall_device_loop_length 2 #define firewall_device_input_command "-i" #define firewall_device_output_command "-o" @@ -188,8 +191,11 @@ extern "C"{ #define firewall_device_output_command_length 2 #define firewall_chain_create_command "-N" + #define firewall_chain_unchain_command "-X" #define firewall_chain_create_command_length 2 + #define firewall_chain_unchain_command_length 2 + enum { firewall_parameter_help, @@ -233,12 +239,7 @@ extern "C"{ typedef struct { f_console_parameter parameters[firewall_total_parameters]; - f_dynamic_string buffer; - f_fss_objects objects; - f_fss_contents contents; - f_string_lengths custom; f_dynamic_strings chains; - f_file_position file_position; f_string_lengths remaining; f_dynamic_strings devices; @@ -248,12 +249,7 @@ extern "C"{ #define firewall_data_initialize \ { \ f_console_parameter_initialize_firewall, \ - f_dynamic_string_initialize, \ - f_fss_objects_initialize, \ - f_fss_contents_initialize, \ - f_string_lengths_initialize, \ f_dynamic_strings_initialize, \ - f_file_position_initialize, \ f_string_lengths_initialize, \ f_dynamic_strings_initialize, \ fll_color_context_initialize, \ diff --git a/level_3/firewall/c/private-firewall.c b/level_3/firewall/c/private-firewall.c index b846bde..50bc90a 100644 --- a/level_3/firewall/c/private-firewall.c +++ b/level_3/firewall/c/private-firewall.c @@ -2,36 +2,37 @@ * Private source file for firewall.c. */ #include +#include "private-firewall.h" -#ifndef _di_firewall_main_ - f_return_status firewall_perform_commands(const f_fss_objects objects, const f_fss_contents contents, const f_bool is_global, const f_string_length this_device, const f_dynamic_string buffer, const firewall_data data, const f_dynamic_string *custom_chain) { - f_status status = f_status_initialize; +#ifndef _di_firewall_perform_commands_ + f_return_status firewall_perform_commands(const firewall_local_data local, const firewall_data data) { + f_status status = f_status_initialize; f_status allocation_status = f_status_initialize; - f_string_length counter = f_string_length_initialize; - f_dynamic_string argument = f_dynamic_string_initialize; + f_string_length i = f_string_length_initialize; + f_dynamic_string argument = f_dynamic_string_initialize; f_dynamic_strings arguments = f_dynamic_strings_initialize; - f_s_int results = 0; - f_string_length length = f_string_length_initialize; - f_bool invalid = f_false; - f_bool is_ip_list = f_false; - f_dynamic_string ip_list = f_dynamic_string_initialize; + f_s_int results = 0; + f_string_length length = f_string_length_initialize; + f_bool invalid = f_false; + f_bool is_ip_list = f_false; + f_dynamic_string ip_list = f_dynamic_string_initialize; // iptables command arguments - f_bool direction_input = f_true; - f_bool direction_output = f_false; - f_bool device_all = f_false; + f_bool direction_input = f_true; + f_bool direction_output = f_false; + f_bool device_all = f_false; f_bool ip_list_direction = f_false; // false = source, true = destination - f_string_length direction = firewall_direction_none_id; - f_dynamic_string device = f_dynamic_string_initialize; - f_string_length action = firewall_action_append_id; + f_string_length direction = firewall_direction_none_id; + f_dynamic_string device = f_dynamic_string_initialize; + f_string_length action = firewall_action_append_id; - if (is_global) { + if (local.is_global) { device_all = f_true; } else { - f_resize_dynamic_string(status, device, data.devices.array[this_device].used); + f_resize_dynamic_string(status, device, data.devices.array[local.device].used); if (f_macro_test_for_allocation_errors(status)) { f_delete_dynamic_string(allocation_status, device); @@ -39,12 +40,12 @@ return status; } - strncat(device.string, data.devices.array[this_device].string, data.devices.array[this_device].used); - device.used = data.devices.array[this_device].used; + strncat(device.string, data.devices.array[local.device].string, data.devices.array[local.device].used); + device.used = data.devices.array[local.device].used; } - for (; counter < objects.used; counter++) { - length = (objects.array[counter].stop - objects.array[counter].start) + 1; + for (; i < local.rule_objects.used; i++) { + length = (local.rule_objects.array[i].stop - local.rule_objects.array[i].start) + 1; invalid = f_false; is_ip_list = f_false; @@ -52,24 +53,24 @@ f_delete_dynamic_string(allocation_status, ip_list); - if (length >= firewall_direction_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_direction, length, firewall_direction_length) == f_equal_to) { - length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1; + if (length >= firewall_direction_length && fl_compare_strings(local.buffer.string + local.rule_objects.array[i].start, (f_string) firewall_direction, length, firewall_direction_length) == f_equal_to) { + length = (local.rule_contents.array[i].array[0].stop - local.rule_contents.array[i].array[0].start) + 1; - if (contents.array[counter].used <= 0 || contents.array[counter].used > 1) { + if (local.rule_contents.array[i].used <= 0 || local.rule_contents.array[i].used > 1) { invalid = f_true; } else { - if (length < firewall_direction_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_input, length, firewall_direction_input_length) == f_not_equal_to) { - if (length < firewall_direction_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_output, length, firewall_direction_output_length) == f_not_equal_to) { - if (length < firewall_direction_forward_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward, length, firewall_direction_forward_length) == f_not_equal_to) { - if (length < firewall_direction_postrouting_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting, length, firewall_direction_postrouting_length) == f_not_equal_to) { - if (length < firewall_direction_prerouting_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting, length, firewall_direction_prerouting_length) == f_not_equal_to) { - if (length < firewall_direction_none_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_none, length, firewall_direction_none_length) == f_not_equal_to) { - if (length < firewall_direction_forward_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward_input, length, firewall_direction_forward_input_length) == f_not_equal_to) { - if (length < firewall_direction_forward_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_forward_output, length, firewall_direction_forward_output_length) == f_not_equal_to) { - if (length < firewall_direction_postrouting_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting_input, length, firewall_direction_postrouting_input_length) == f_not_equal_to) { - if (length < firewall_direction_postrouting_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_postrouting_output, length, firewall_direction_postrouting_output_length) == f_not_equal_to) { - if (length < firewall_direction_prerouting_input_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting_input, length, firewall_direction_prerouting_input_length) == f_not_equal_to) { - if (length < firewall_direction_prerouting_output_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_direction_prerouting_output, length, firewall_direction_prerouting_output_length) == f_not_equal_to) { + if (length < firewall_direction_input_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_input, length, firewall_direction_input_length) == f_not_equal_to) { + if (length < firewall_direction_output_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_output, length, firewall_direction_output_length) == f_not_equal_to) { + if (length < firewall_direction_forward_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_forward, length, firewall_direction_forward_length) == f_not_equal_to) { + if (length < firewall_direction_postrouting_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_postrouting, length, firewall_direction_postrouting_length) == f_not_equal_to) { + if (length < firewall_direction_prerouting_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_prerouting, length, firewall_direction_prerouting_length) == f_not_equal_to) { + if (length < firewall_direction_none_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_none, length, firewall_direction_none_length) == f_not_equal_to) { + if (length < firewall_direction_forward_input_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_forward_input, length, firewall_direction_forward_input_length) == f_not_equal_to) { + if (length < firewall_direction_forward_output_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_forward_output, length, firewall_direction_forward_output_length) == f_not_equal_to) { + if (length < firewall_direction_postrouting_input_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_postrouting_input, length, firewall_direction_postrouting_input_length) == f_not_equal_to) { + if (length < firewall_direction_postrouting_output_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_postrouting_output, length, firewall_direction_postrouting_output_length) == f_not_equal_to) { + if (length < firewall_direction_prerouting_input_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_prerouting_input, length, firewall_direction_prerouting_input_length) == f_not_equal_to) { + if (length < firewall_direction_prerouting_output_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_direction_prerouting_output, length, firewall_direction_prerouting_output_length) == f_not_equal_to) { invalid = f_true; } else { direction_input = f_false; @@ -134,23 +135,23 @@ } if (!invalid) continue; - } else if (length >= firewall_device_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_device, length, firewall_device_length) == f_equal_to) { - length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1; + } else if (length >= firewall_device_length && fl_compare_strings(local.buffer.string + local.rule_objects.array[i].start, (f_string) firewall_device, length, firewall_device_length) == f_equal_to) { + length = (local.rule_contents.array[i].array[0].stop - local.rule_contents.array[i].array[0].start) + 1; - if (contents.array[counter].used <= 0 || contents.array[counter].used > 1) { + if (local.rule_contents.array[i].used <= 0 || local.rule_contents.array[i].used > 1) { invalid = f_true; - } else if (length >= firewall_device_all_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_equal_to) { + } else if (length >= firewall_device_all_length && fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_equal_to) { f_delete_dynamic_string(status, device); device_all = f_true; continue; - } else if (length >= firewall_device_this_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_this, length, firewall_device_this_length) == f_equal_to) { + } else if (length >= firewall_device_this_length && fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_device_this, length, firewall_device_this_length) == f_equal_to) { f_delete_dynamic_string(status, device); - f_resize_dynamic_string(status, device, data.devices.array[this_device].used); + f_resize_dynamic_string(status, device, data.devices.array[local.device].used); if (f_macro_test_for_allocation_errors(status)) break; - strncat(device.string, data.devices.array[this_device].string, data.devices.array[this_device].used); - device.used = data.devices.array[this_device].used; + strncat(device.string, data.devices.array[local.device].string, data.devices.array[local.device].used); + device.used = data.devices.array[local.device].used; device_all = f_false; continue; } @@ -161,20 +162,20 @@ if (f_macro_test_for_allocation_errors(status)) break; - strncat(device.string, buffer.string + contents.array[counter].array[0].start, length); + strncat(device.string, local.buffer.string + local.rule_contents.array[i].array[0].start, length); device.used = length; device_all = f_false; continue; } - } else if (length >= firewall_action_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_action, length, firewall_action_length) == f_equal_to) { - length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1; + } else if (length >= firewall_action_length && fl_compare_strings(local.buffer.string + local.rule_objects.array[i].start, (f_string) firewall_action, length, firewall_action_length) == f_equal_to) { + length = (local.rule_contents.array[i].array[0].stop - local.rule_contents.array[i].array[0].start) + 1; - if (contents.array[counter].used <= 0 || contents.array[counter].used > 1) { + if (local.rule_contents.array[i].used <= 0 || local.rule_contents.array[i].used > 1) { invalid = f_true; - } else if (length < firewall_action_append_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_append, length, firewall_action_append_length) == f_not_equal_to) { - if (length < firewall_action_insert_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_insert, length, firewall_action_insert_length) == f_not_equal_to) { - if (length < firewall_action_policy_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_policy, length, firewall_action_policy_length) == f_not_equal_to) { - if (length < firewall_action_none_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_action_none, length, firewall_action_none_length) == f_not_equal_to) { + } else if (length < firewall_action_append_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_action_append, length, firewall_action_append_length) == f_not_equal_to) { + if (length < firewall_action_insert_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_action_insert, length, firewall_action_insert_length) == f_not_equal_to) { + if (length < firewall_action_policy_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_action_policy, length, firewall_action_policy_length) == f_not_equal_to) { + if (length < firewall_action_none_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_action_none, length, firewall_action_none_length) == f_not_equal_to) { invalid = f_true; } else { action = firewall_action_none_id; @@ -190,26 +191,26 @@ } if (!invalid) continue; - } else if (length >= firewall_ip_list_length && fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_ip_list, length, firewall_ip_list_length) == f_equal_to) { - length = (contents.array[counter].array[0].stop - contents.array[counter].array[0].start) + 1; + } else if (length >= firewall_ip_list_length && fl_compare_strings(local.buffer.string + local.rule_objects.array[i].start, (f_string) firewall_ip_list, length, firewall_ip_list_length) == f_equal_to) { + length = (local.rule_contents.array[i].array[0].stop - local.rule_contents.array[i].array[0].start) + 1; is_ip_list = f_true; - if (length >= firewall_ip_list_source_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_ip_list_source, length, firewall_ip_list_source_length) == f_equal_to) { + if (length >= firewall_ip_list_source_length && fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_ip_list_source, length, firewall_ip_list_source_length) == f_equal_to) { ip_list_direction = f_false; - } else if (length >= firewall_ip_list_destination_length && fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_ip_list_destination, length, firewall_ip_list_destination_length) == f_equal_to) { + } else if (length >= firewall_ip_list_destination_length && fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_ip_list_destination, length, firewall_ip_list_destination_length) == f_equal_to) { ip_list_direction = f_true; } else { invalid = f_true; } - } else if (length < firewall_rule_length || fl_compare_strings(buffer.string + objects.array[counter].start, (f_string) firewall_rule, length, firewall_rule_length) == f_not_equal_to) { + } else if (length < firewall_rule_length || fl_compare_strings(local.buffer.string + local.rule_objects.array[i].start, (f_string) firewall_rule, length, firewall_rule_length) == f_not_equal_to) { if (length > 0) { fl_print_color_code(f_standard_warning, data.context.warning); - fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter); - f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, length); + fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) i); + f_print_string(f_standard_warning, local.buffer.string + local.rule_objects.array[i].start, length); fprintf(f_standard_warning, "' is invalid"); fl_print_color_code(f_standard_warning, data.context.reset); } else { - fprintf(f_standard_warning, "WARNING: At line %u, the object is missing", (unsigned int) counter); + fprintf(f_standard_warning, "WARNING: At line %u, the object is missing", (unsigned int) i); } fprintf(f_standard_warning, "\n"); @@ -217,25 +218,24 @@ } if (invalid) { - length = (objects.array[counter].stop - objects.array[counter].start) + 1; + length = (local.rule_objects.array[i].stop - local.rule_objects.array[i].start) + 1; if (length > 0) { fl_print_color_code(f_standard_warning, data.context.warning); - fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter); - f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, length); + fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) i); + f_print_string(f_standard_warning, local.buffer.string + local.rule_objects.array[i].start, length); fprintf(f_standard_warning, "' has invalid content '"); - f_print_string(f_standard_warning, buffer.string + contents.array[counter].array[0].start, contents.array[counter].array[0].stop - contents.array[counter].array[0].start + 1); + f_print_string(f_standard_warning, local.buffer.string + local.rule_contents.array[i].array[0].start, local.rule_contents.array[i].array[0].stop - local.rule_contents.array[i].array[0].start + 1); fprintf(f_standard_warning, "'"); fl_print_color_code(f_standard_warning, data.context.reset); fprintf(f_standard_warning, "\n"); } else { - fl_print_color_line(f_standard_warning, data.context.warning, data.context.reset, "WARNING: At line %u, the object has no content", (unsigned int) counter); + fl_print_color_line(f_standard_warning, data.context.warning, data.context.reset, "WARNING: At line %u, the object has no content", (unsigned int) i); } continue; } - // first add the program name f_delete_dynamic_strings(status, arguments); f_resize_dynamic_strings(status, arguments, arguments.used + 1); @@ -298,14 +298,16 @@ argument.used = 0; } + if (action != firewall_action_none_id) { - if (custom_chain != f_null) { - f_resize_dynamic_string(status, argument, custom_chain->used); + if (!(local.is_main || local.is_stop || local.is_lock)) { + f_resize_dynamic_string(status, argument, data.chains.array[local.chain_ids.array[local.chain]].used); if (f_macro_test_for_allocation_errors(status)) break; - strncat(argument.string, custom_chain->string, custom_chain->used); - argument.used = custom_chain->used; + strncat(argument.string, data.chains.array[local.chain_ids.array[local.chain]].string, data.chains.array[local.chain_ids.array[local.chain]].used); + argument.used = data.chains.array[local.chain].used; + } else if (direction == firewall_direction_forward_id) { f_resize_dynamic_string(status, argument, firewall_direction_forward_command_length); @@ -359,7 +361,7 @@ } if (device.used > 0) { - if (length < firewall_device_all_length || fl_compare_strings(buffer.string + contents.array[counter].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_not_equal_to) { + if (length < firewall_device_all_length || fl_compare_strings(local.buffer.string + local.rule_contents.array[i].array[0].start, (f_string) firewall_device_all, length, firewall_device_all_length) == f_not_equal_to) { if (direction_input) { f_resize_dynamic_string(status, argument, firewall_device_input_command_length); if (f_macro_test_for_allocation_errors(status)) break; @@ -413,35 +415,35 @@ } // last up is the "rule" - if ((!is_ip_list && contents.array[counter].used > 0) || (is_ip_list && contents.array[counter].used > 1)) { + if ((!is_ip_list && local.rule_contents.array[i].used > 0) || (is_ip_list && local.rule_contents.array[i].used > 1)) { f_string_length subcounter = f_string_length_initialize; if (is_ip_list) { // skip past the direction subcounter++; - length = (contents.array[counter].array[subcounter].stop - contents.array[counter].array[subcounter].start) + 1; + length = (local.rule_contents.array[i].array[subcounter].stop - local.rule_contents.array[i].array[subcounter].start) + 1; f_resize_dynamic_string(status, ip_list, length); if (f_macro_test_for_allocation_errors(status)) { - subcounter = contents.array[counter].used; + subcounter = local.rule_contents.array[i].used; } else { - strncat(ip_list.string, buffer.string + contents.array[counter].array[subcounter].start, length); + strncat(ip_list.string, local.buffer.string + local.rule_contents.array[i].array[subcounter].start, length); ip_list.used = length; subcounter++; } } - for (; subcounter < contents.array[counter].used; subcounter++) { - length = (contents.array[counter].array[subcounter].stop - contents.array[counter].array[subcounter].start) + 1; + for (; subcounter < local.rule_contents.array[i].used; subcounter++) { + length = (local.rule_contents.array[i].array[subcounter].stop - local.rule_contents.array[i].array[subcounter].start) + 1; f_resize_dynamic_string(status, argument, length); if (f_macro_test_for_allocation_errors(status)) break; - strncat(argument.string, buffer.string + contents.array[counter].array[subcounter].start, length); + strncat(argument.string, local.buffer.string + local.rule_contents.array[i].array[subcounter].start, length); argument.used = length; if (length > 0) { @@ -459,11 +461,11 @@ } } } else { - length = (objects.array[counter].stop - objects.array[counter].start) + 1; + length = (local.rule_objects.array[i].stop - local.rule_objects.array[i].start) + 1; fl_print_color_code(f_standard_warning, data.context.warning); - fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) counter); - f_print_string(f_standard_warning, buffer.string + objects.array[counter].start, objects.array[counter].stop - objects.array[counter].start + 1); + fprintf(f_standard_warning, "WARNING: At line %u, the object '", (unsigned int) i); + f_print_string(f_standard_warning, local.buffer.string + local.rule_objects.array[i].start, local.rule_objects.array[i].stop - local.rule_objects.array[i].start + 1); fprintf(f_standard_warning, "' has no content"); fl_print_color_code(f_standard_warning, data.context.reset); fprintf(f_standard_warning, "\n"); @@ -703,4 +705,351 @@ return status; } -#endif // _di_firewall_main_ +#endif // _di_firewall_perform_commands_ + +#ifndef _di_firewall_create_custom_chains_ + f_return_status firewall_create_custom_chains(firewall_reserved_chains *reserved, firewall_local_data *local, firewall_data *data) { + f_status status = f_none; + f_status status2 = f_none; + + f_bool new_chain = f_false; + f_s_int results = 0; + + f_array_length i = f_array_length_initialize; + f_array_length j = f_array_length_initialize; + + f_string_length length = f_string_length_initialize; + f_string_location location = f_string_location_initialize; + f_dynamic_strings arguments = f_dynamic_strings_initialize; + + f_dynamic_string static_string = f_dynamic_string_initialize; + + f_resize_array_lengths(status, local->chain_ids, local->chain_objects.used); + + local->chain_ids.used = 0; + + if (f_macro_test_for_allocation_errors(status)) { + return status; + } + + f_resize_dynamic_strings(status, arguments, 3); + + if (f_macro_test_for_allocation_errors(status)) { + return status; + } + + f_resize_dynamic_string(status, arguments.array[0], firewall_program_name_length); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + + f_resize_dynamic_string(status, arguments.array[1], firewall_chain_create_command_length); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + + reserved->has_lock = f_false; + reserved->has_stop = f_false; + reserved->has_main = f_false; + + strncat(arguments.array[0].string, firewall_program_name, firewall_program_name_length); + strncat(arguments.array[1].string, firewall_chain_create_command, firewall_chain_create_command_length); + arguments.array[0].used = firewall_program_name_length; + arguments.array[1].used = firewall_chain_create_command_length; + arguments.used = 3; + + while (i < local->chain_objects.used) { + new_chain = f_true; + j = 0; + + // skip globally reserved chain name: main + location.start = 0; + location.stop = firewall_group_main_length - 1; + static_string.string = firewall_group_main; + static_string.used = firewall_group_main_length; + if (fl_compare_partial_dynamic_strings(local->buffer, static_string, local->chain_objects.array[i], location) == f_equal_to) { + new_chain = f_false; + reserved->has_main = f_true; + reserved->main_at = i; + } + + // skip globally reserved chain name: stop + location.start = 0; + location.stop = firewall_group_stop_length - 1; + static_string.string = firewall_group_stop; + static_string.used = firewall_group_stop_length; + if (fl_compare_partial_dynamic_strings(local->buffer, static_string, local->chain_objects.array[i], location) == f_equal_to) { + new_chain = f_false; + reserved->has_stop = f_true; + reserved->stop_at = i; + } + + // skip globally reserved chain name: lock + location.start = 0; + location.stop = firewall_group_lock_length - 1; + static_string.string = firewall_group_lock; + static_string.used = firewall_group_lock_length; + if (fl_compare_partial_dynamic_strings(local->buffer, static_string, local->chain_objects.array[i], location) == f_equal_to) { + new_chain = f_false; + reserved->has_lock = f_true; + reserved->lock_at = i; + } + + // nullify the static string + static_string.string = f_null; + static_string.used = 0; + + if (new_chain) { + while (j < data->chains.used) { + location.start = 0; + location.stop = data->chains.array[j].used - 1; + + if (fl_compare_partial_dynamic_strings(local->buffer, data->chains.array[j], local->chain_objects.array[i], location) == f_equal_to) { + new_chain = f_false; + local->chain_ids.array[i] = j; + + break; + } + + j++; + } // while + } + + if (new_chain) { + length = local->chain_objects.array[i].stop - local->chain_objects.array[i].start + 1; + + if (data->chains.used >= data->chains.size) { + f_resize_dynamic_strings(status, data->chains, data->chains.used + firewall_default_allocation_step); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + } + + if (length >= arguments.array[2].size) { + f_resize_dynamic_string(status, arguments.array[2], length + firewall_default_allocation_step); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + } + + f_resize_dynamic_string(status, data->chains.array[data->chains.used], length); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + + data->chains.array[data->chains.used].used = 0; + local->chain_ids.array[i] = data->chains.used; + arguments.array[2].used = 0; + j = local->chain_objects.array[i].start; + + while (j <= local->chain_objects.array[i].stop) { + if (local->buffer.string[j] == f_fss_delimit_placeholder) { + j++; + continue; + } + + data->chains.array[data->chains.used].string[data->chains.array[data->chains.used].used] = local->buffer.string[j]; + data->chains.array[data->chains.used].used++; + arguments.array[2].string[arguments.array[2].used] = local->buffer.string[j]; + arguments.array[2].used++; + j++; + } // while + + f_resize_dynamic_string(status, data->chains.array[data->chains.used], data->chains.array[data->chains.used].used); + + if (f_macro_test_for_allocation_errors(status)) { + f_delete_dynamic_strings(status2, arguments); + + return status; + } + + status = fll_execute_program((f_string) firewall_program_name, arguments, &results); + + if (status == f_failure) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Failed to perform requested %s operation:", firewall_program_name); + fprintf(f_standard_error, " "); + + f_string_length i = f_string_length_initialize; + + fl_print_color_code(f_standard_error, data->context.error); + + for (; i < arguments.used; i++) { + fprintf(f_standard_error, "%s ", arguments.array[i].string); + } + + fl_print_color_code(f_standard_error, data->context.reset); + fprintf(f_standard_error, "\n"); + + f_delete_dynamic_strings(status2, arguments); + + return status; + } else if (status == f_invalid_parameter) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_execute_path()"); + f_delete_dynamic_strings(status2, arguments); + + return status; + } + + data->chains.used++; + } + + i++; + } // while + + return status; + } +#endif // _di_firewall_create_custom_chains_ + +#ifndef _di_firewall_process_rules_ + f_return_status firewall_buffer_rules(const f_string filename, const f_bool optional, firewall_local_data *local, firewall_data *data) { + f_file file = f_file_initialize; + f_status status = f_none; + + status = f_file_open(&file, filename); + + if (optional && status != f_none) { + if (status == f_invalid_parameter) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()."); + } else if (status != f_file_not_found && status != f_file_open_error && status != f_file_descriptor_error) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open().", status); + } + + return status; + } else if (status != f_none) { + if (status == f_invalid_parameter) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling f_file_open()."); + } else if (status == f_file_not_found) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to find the file '%s'.", filename); + } else if (status == f_file_open_error) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Unable to open the file '%s'.", filename); + } else if (status == f_file_descriptor_error) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: File descriptor error while trying to open the file '%s'.", filename); + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling f_file_open().", status); + } + + return status; + } + + f_macro_file_reset_position(local->file_position, file) + status = fl_file_read(file, local->file_position, &local->buffer); + + f_file_close(&file); + + if (status != f_none && status != f_none_on_eof) { + if (status == f_invalid_parameter) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fl_file_read()."); + } else if (status == f_overflow) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: Integer overflow while trying to buffer the file '%s'.", filename); + } else if (status == f_file_not_open) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: The file '%s' is no longer open.", filename); + } else if (status == f_file_seek_error) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A seek error occurred while accessing the file '%s'.", filename); + } else if (status == f_file_read_error) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: A read error occurred while accessing the file '%s'.", filename); + } else if (f_macro_test_for_allocation_errors(status)) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory."); + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fl_file_read().", status); + } + + return status; + } else { + f_string_location input = f_string_location_initialize; + + input.stop = local->buffer.used - 1; + + status = fll_fss_basic_list_read(&local->buffer, &input, &local->chain_objects, &local->chain_contents); + } + + if (status != f_none && status != f_none_on_eos && status != f_none_on_stop && status != fl_fss_found_object_no_content) { + if (status == f_invalid_parameter) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: Invalid parameter when calling fll_fss_basic_list_read() for the file '%s'.", filename); + } else if (status == f_no_data_on_eos || status == f_no_data || status == f_no_data_on_stop) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "ERROR: No relevant data was found within the file '%s'.", filename); + } else if (f_macro_test_for_allocation_errors(status)) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory."); + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling fll_fss_basic_list_read() for the file '%s'.", status, filename); + } + + return status; + } + + return status; + } +#endif // _di_firewall_buffer_rules_ + +#ifndef _di_firewall_process_rules_ + f_return_status firewall_process_rules(f_string_location *input, firewall_local_data *local, firewall_data *data) { + f_status status = f_none; + f_status status2 = f_none; + + status = fll_fss_extended_read(&local->buffer, input, &local->rule_objects, &local->rule_contents); + + + if (status == f_none || status == f_none_on_stop || status == f_none_on_eos) { + status = firewall_perform_commands(*local, *data); + + if (status != f_none) { + if (f_macro_test_for_allocation_errors(status)) { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "CRITICAL ERROR: unable to allocate memory.", status); + } else if (status == f_failure) { + // the error message has already been displayed. + } else { + fl_print_color_line(f_standard_error, data->context.error, data->context.reset, "INTERNAL ERROR: An unhandled error (%u) has occured while calling firewall_perform_commands().", status); + } + + f_delete_fss_objects(status2, local->rule_objects); + f_delete_fss_contents(status2, local->rule_contents); + return status; + } + } + + f_delete_fss_objects(status2, local->rule_objects); + f_delete_fss_contents(status2, local->rule_contents); + return status; + } +#endif // _di_firewall_process_rules_ + +#ifndef _di_firewall_delete_local_data_ + f_return_status firewall_delete_local_data(firewall_local_data *local) { + f_status status = f_status_initialize; + + local->is_global = f_true; + local->is_main = f_false; + local->is_stop = f_false; + local->is_lock = f_false; + + local->file_position.buffer_start = 0; + local->file_position.file_start = 0; + local->file_position.total_elements = 0; + + local->device = 0; + local->chain = 0; + + f_delete_dynamic_string(status, local->buffer); + f_delete_array_lengths(status, local->chain_ids); + f_delete_fss_objects(status, local->chain_objects); + f_delete_fss_contents(status, local->chain_contents); + f_delete_fss_objects(status, local->rule_objects); + f_delete_fss_contents(status, local->rule_contents); + + return f_none; + } +#endif // _di_firewall_delete_local_data_ diff --git a/level_3/firewall/c/private-firewall.h b/level_3/firewall/c/private-firewall.h index cd37595..66b6883 100644 --- a/level_3/firewall/c/private-firewall.h +++ b/level_3/firewall/c/private-firewall.h @@ -2,6 +2,102 @@ * Private include file for firewall.c. */ -#ifndef _di_firewall_main_ - f_return_status firewall_perform_commands(const f_fss_objects objects, const f_fss_contents contents, const f_bool is_global, const f_string_length this_device, const f_dynamic_string buffer, const firewall_data data, const f_dynamic_string *custom_chain) __attribute__((visibility("internal"))); -#endif // _di_firewall_main_ +#ifndef _PRIVATE_firewall_h +#define _PRIVATE_firewall_h + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef _di_firewall_local_data_ + typedef struct { + f_bool is_global; + f_bool is_main; + f_bool is_stop; + f_bool is_lock; + + f_file_position file_position; + + f_array_length device; + + f_dynamic_string buffer; + f_array_length chain; + f_array_lengths chain_ids; + f_fss_objects chain_objects; + f_fss_contents chain_contents; + f_fss_objects rule_objects; + f_fss_contents rule_contents; + } firewall_local_data; + + #define firewall_local_data_initialize \ + { \ + f_true, \ + f_false, \ + f_false, \ + f_false, \ + f_file_position_initialize, \ + 0, \ + f_dynamic_string_initialize, \ + 0, \ + f_array_lengths_initialize, \ + f_fss_objects_initialize, \ + f_fss_contents_initialize, \ + f_fss_objects_initialize, \ + f_fss_contents_initialize, \ + } +#endif // _di_firewall_local_data_ + +#ifndef _di_firewall_reserved_chains_ + typedef struct { + f_bool has_main; + f_bool has_stop; + f_bool has_lock; + + f_array_length main_at; + f_array_length stop_at; + f_array_length lock_at; + } firewall_reserved_chains; + + #define firewall_reserved_chains_initialize \ + { \ + f_false, \ + f_false, \ + f_false, \ + 0, \ + 0, \ + 0, \ + } +#endif // _di_firewall_reserved_chains_ + +#ifndef _di_firewall_macro_private_ + #define firewall_macro_delete_fss_buffers(status, buffer, objects, contents) \ + f_delete_dynamic_string(status, buffer); \ + f_delete_fss_objects(status, objects); \ + f_delete_fss_contents(status, contents); +#endif // _di_firewall_macro_private_ + +#ifndef _di_firewall_perform_commands_ + f_return_status firewall_perform_commands(const firewall_local_data local, const firewall_data data) __attribute__((visibility("internal"))); +#endif // _di_firewall_perform_commands_ + +#ifndef _di_firewall_create_custom_chains_ + f_return_status firewall_create_custom_chains(firewall_reserved_chains *reserved, firewall_local_data *local, firewall_data *data) __attribute__((visibility("internal"))); +#endif // _di_firewall_create_custom_chains_ + +#ifndef _di_firewall_buffer_rules_ + f_return_status firewall_buffer_rules(const f_string filename, const f_bool optional, firewall_local_data *local, firewall_data *data) __attribute__((visibility("internal"))); +#endif // _di_firewall_buffer_rules_ + +#ifndef _di_firewall_process_rules_ + f_return_status firewall_process_rules(f_string_location *input, firewall_local_data *local, firewall_data *data) __attribute__((visibility("internal"))); +#endif // _di_firewall_process_rules_ + +#ifndef _di_firewall_delete_local_data_ + f_return_status firewall_delete_local_data(firewall_local_data *local) __attribute__((visibility("internal"))); +#endif // _di_firewall_delete_local_data_ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _PRIVATE_firewall_h