679 lines
17 KiB
C
679 lines
17 KiB
C
|
/*
|
||
|
* Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License version 2
|
||
|
* as published by the Free Software Foundation.
|
||
|
*/
|
||
|
|
||
|
#include <limits.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include "include/defex_rules.h"
|
||
|
|
||
|
#define SAFE_STRCOPY(dst, src) do { strncpy(dst, src, sizeof(dst)); dst[sizeof(dst) - 1] = 0; } while(0)
|
||
|
|
||
|
const struct feature_match_entry feature_match[] = {
|
||
|
{"feature_safeplace_path", feature_safeplace_path},
|
||
|
{"feature_ped_exception", feature_ped_exception},
|
||
|
{"feature_immutable_path_open", feature_immutable_path_open},
|
||
|
{"feature_immutable_path_write", feature_immutable_path_write},
|
||
|
{"feature_immutable_src_exception", feature_immutable_src_exception},
|
||
|
{"feature_umhbin_path", feature_umhbin_path},
|
||
|
{"feature_integrity_check", feature_integrity_check},
|
||
|
};
|
||
|
|
||
|
const int feature_match_size = sizeof(feature_match) / sizeof(feature_match[0]);
|
||
|
|
||
|
struct file_list_item {
|
||
|
char file_name[PATH_MAX];
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
char integrity[INTEGRITY_LENGTH * 2 + 1];
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
int is_recovery;
|
||
|
};
|
||
|
|
||
|
struct rule_item_struct *defex_packed_rules;
|
||
|
int packfiles_count, packfiles_size;
|
||
|
|
||
|
struct file_list_item *file_list = NULL;
|
||
|
int file_list_count = 0;
|
||
|
|
||
|
#ifndef DEFEX_DEBUG_ENABLE
|
||
|
int debug_ifdef_is_active = 0;
|
||
|
void process_debug_ifdef(const char *src_str);
|
||
|
#endif
|
||
|
|
||
|
/* Suplementary functions for packing rules */
|
||
|
struct rule_item_struct *create_file_item(const char *name, int l);
|
||
|
struct rule_item_struct *add_file_item(struct rule_item_struct *base, const char *name, int l);
|
||
|
struct rule_item_struct *lookup_dir(struct rule_item_struct *base, const char *name, int l, int for_recovery);
|
||
|
struct rule_item_struct *add_file_path(const char *file_path, int for_recovery);
|
||
|
struct rule_item_struct *addline2tree(char *src_line, enum feature_types feature);
|
||
|
char *extract_rule_text(const char *src_line);
|
||
|
int lookup_tree(const char *file_path, int attribute, int for_recovery);
|
||
|
int store_tree(FILE *f, FILE *f_bin);
|
||
|
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
/* Transfer string to hex */
|
||
|
unsigned char ascii_to_hex(unsigned char input);
|
||
|
int string_to_hex(unsigned char *input, size_t inputLen, unsigned char *output);
|
||
|
char null_integrity[INTEGRITY_LENGTH * 2 + 1];
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
|
||
|
/* Suplementary functions for reducing rules */
|
||
|
int remove_substr(char *str, const char *part);
|
||
|
void trim_cr_lf(char *str);
|
||
|
char* remove_redundant_chars(char *str);
|
||
|
int load_file_list(const char *name);
|
||
|
int lookup_file_list(const char *rule, int for_recovery);
|
||
|
|
||
|
/* Main processing functions */
|
||
|
int reduce_rules(const char *source_rules_file, const char *reduced_rules_file, const char *list_file);
|
||
|
int pack_rules(const char *source_rules_file, const char *packed_rules_file, const char *packed_rules_binfile);
|
||
|
|
||
|
|
||
|
struct rule_item_struct *create_file_item(const char *name, int l)
|
||
|
{
|
||
|
struct rule_item_struct *item;
|
||
|
unsigned int offset;
|
||
|
|
||
|
if (!name)
|
||
|
l = 0;
|
||
|
offset = packfiles_size;
|
||
|
packfiles_size += (sizeof(struct rule_item_struct) + l);
|
||
|
packfiles_count++;
|
||
|
item = GET_ITEM_PTR(offset, defex_packed_rules);
|
||
|
item->next_file = 0;
|
||
|
item->next_level = 0;
|
||
|
item->feature_type = 0;
|
||
|
item->size = l;
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
memset(item->integrity, 0, INTEGRITY_LENGTH);
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
if (l)
|
||
|
memcpy(item->name, name, l);
|
||
|
return item;
|
||
|
}
|
||
|
|
||
|
struct rule_item_struct *add_file_item(struct rule_item_struct *base, const char *name, int l)
|
||
|
{
|
||
|
struct rule_item_struct *item, *new_item = NULL;
|
||
|
|
||
|
if (!base)
|
||
|
return new_item;
|
||
|
|
||
|
new_item = create_file_item(name, l);
|
||
|
if (!base->next_level) {
|
||
|
base->next_level = GET_ITEM_OFFSET(new_item);
|
||
|
} else {
|
||
|
item = GET_ITEM_PTR(base->next_level, defex_packed_rules);
|
||
|
while(item->next_file) {
|
||
|
item = GET_ITEM_PTR(item->next_file, defex_packed_rules);
|
||
|
}
|
||
|
item->next_file = GET_ITEM_OFFSET(new_item);
|
||
|
}
|
||
|
return new_item;
|
||
|
}
|
||
|
|
||
|
struct rule_item_struct *lookup_dir(struct rule_item_struct *base, const char *name, int l, int for_recovery)
|
||
|
{
|
||
|
struct rule_item_struct *item = NULL;
|
||
|
unsigned int offset;
|
||
|
|
||
|
if (!base || !base->next_level)
|
||
|
return item;
|
||
|
item = GET_ITEM_PTR(base->next_level, defex_packed_rules);
|
||
|
do {
|
||
|
if ((!(item->feature_type & feature_is_file)
|
||
|
|| (!!(item->feature_type & feature_for_recovery)) == for_recovery)
|
||
|
&& item->size == l
|
||
|
&& !memcmp(name, item->name, l)) return item;
|
||
|
offset = item->next_file;
|
||
|
item = GET_ITEM_PTR(offset, defex_packed_rules);
|
||
|
} while(offset);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
struct rule_item_struct *add_file_path(const char *file_path, int for_recovery)
|
||
|
{
|
||
|
const char *ptr, *next_separator;
|
||
|
struct rule_item_struct *base, *cur_item = NULL;
|
||
|
int l;
|
||
|
|
||
|
if (!file_path || *file_path != '/')
|
||
|
return NULL;
|
||
|
if (!defex_packed_rules) {
|
||
|
packfiles_count = 0;
|
||
|
packfiles_size = 0;
|
||
|
defex_packed_rules = calloc(sizeof(struct rule_item_struct), 100 * 1024);
|
||
|
if (!defex_packed_rules) {
|
||
|
printf("WARNING: Can not create the new item!\n");
|
||
|
exit(-1);
|
||
|
}
|
||
|
create_file_item("DEFEX_RULES_FILE", 16);
|
||
|
}
|
||
|
base = defex_packed_rules;
|
||
|
ptr = file_path + 1;
|
||
|
do {
|
||
|
next_separator = strchr(ptr, '/');
|
||
|
if (!next_separator)
|
||
|
l = strlen(ptr);
|
||
|
else
|
||
|
l = next_separator - ptr;
|
||
|
if (!l)
|
||
|
return NULL; /* two slashes in sequence */
|
||
|
cur_item = lookup_dir(base, ptr, l, for_recovery);
|
||
|
if (!cur_item) {
|
||
|
cur_item = add_file_item(base, ptr, l);
|
||
|
/* slash wasn't found, it's a file */
|
||
|
if (!next_separator) {
|
||
|
cur_item->feature_type |= feature_is_file;
|
||
|
if (for_recovery)
|
||
|
cur_item->feature_type |= feature_for_recovery;
|
||
|
}
|
||
|
}
|
||
|
base = cur_item;
|
||
|
ptr += l;
|
||
|
if (next_separator)
|
||
|
ptr++;
|
||
|
} while(*ptr);
|
||
|
return cur_item;
|
||
|
}
|
||
|
|
||
|
int lookup_tree(const char *file_path, int attribute, int for_recovery)
|
||
|
{
|
||
|
const char *ptr, *next_separator;
|
||
|
struct rule_item_struct *base, *cur_item = NULL;
|
||
|
int l;
|
||
|
|
||
|
if (!file_path || *file_path != '/' || !defex_packed_rules)
|
||
|
return 0;
|
||
|
base = defex_packed_rules;
|
||
|
ptr = file_path + 1;
|
||
|
do {
|
||
|
next_separator = strchr(ptr, '/');
|
||
|
if (!next_separator)
|
||
|
l = strlen(ptr);
|
||
|
else
|
||
|
l = next_separator - ptr;
|
||
|
if (!l)
|
||
|
return 0;
|
||
|
cur_item = lookup_dir(base, ptr, l, for_recovery);
|
||
|
if (!cur_item)
|
||
|
break;
|
||
|
if (cur_item->feature_type & attribute)
|
||
|
return 1;
|
||
|
base = cur_item;
|
||
|
ptr += l;
|
||
|
if (next_separator)
|
||
|
ptr++;
|
||
|
} while(*ptr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char *extract_rule_text(const char *src_line)
|
||
|
{
|
||
|
char *start_ptr, *end_ptr;
|
||
|
|
||
|
start_ptr = strchr(src_line, '\"');
|
||
|
if (start_ptr) {
|
||
|
start_ptr++;
|
||
|
end_ptr = strchr(start_ptr, '\"');
|
||
|
if (end_ptr) {
|
||
|
*end_ptr = 0;
|
||
|
return start_ptr;
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
unsigned char ascii_to_hex(unsigned char input)
|
||
|
{
|
||
|
if (input >= 0x30 && input <=0x39)
|
||
|
return input - 0x30;
|
||
|
else if (input >= 0x41 && input <= 0x46)
|
||
|
return input - 0x37;
|
||
|
else if (input >= 0x61 && input <= 0x66)
|
||
|
return input - 0x57;
|
||
|
else
|
||
|
return 0xFF;
|
||
|
}
|
||
|
|
||
|
int string_to_hex(unsigned char *input, size_t inputLen, unsigned char *output)
|
||
|
{
|
||
|
unsigned char convert1, convert2;
|
||
|
size_t i;
|
||
|
|
||
|
if (input == NULL || output == NULL)
|
||
|
return 0;
|
||
|
|
||
|
// Check input is a paired value.
|
||
|
if (inputLen % 2 != 0)
|
||
|
return 0;
|
||
|
|
||
|
// Convert ascii code to hexa.
|
||
|
for (i = 0; i < inputLen / 2; i++) {
|
||
|
convert1 = ascii_to_hex(input[2*i]);
|
||
|
convert2 = ascii_to_hex(input[2*i+1]);
|
||
|
|
||
|
if (convert1 == 0xFF || convert2 == 0xFF)
|
||
|
return 0;
|
||
|
|
||
|
output[i] = (char)((convert1 << 4) | convert2);
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
|
||
|
struct rule_item_struct *addline2tree(char *src_line, enum feature_types feature)
|
||
|
{
|
||
|
struct rule_item_struct *item = NULL;
|
||
|
char *str;
|
||
|
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
unsigned char *integrity, *n_sign = NULL, *r_sign = NULL;
|
||
|
int value;
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
|
||
|
str = extract_rule_text(src_line);
|
||
|
if (!str)
|
||
|
return NULL;
|
||
|
|
||
|
#ifndef DEFEX_INTEGRITY_ENABLE
|
||
|
item = add_file_path(str, 0);
|
||
|
if (item)
|
||
|
item->feature_type |= feature;
|
||
|
#else
|
||
|
integrity = (unsigned char *)extract_rule_text(str + strnlen(str, PATH_MAX) + 1);
|
||
|
if (integrity) {
|
||
|
n_sign = (unsigned char *)strchr((const char *)integrity, 'N');
|
||
|
r_sign = (unsigned char *)strchr((const char *)integrity, 'R');
|
||
|
}
|
||
|
if (!(n_sign == NULL && r_sign != NULL)) {
|
||
|
item = add_file_path(str, 0);
|
||
|
if (item) {
|
||
|
item->feature_type |= feature;
|
||
|
if (n_sign) {
|
||
|
value = string_to_hex(n_sign + 1, INTEGRITY_LENGTH * 2, item->integrity);
|
||
|
if (!value)
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
if (r_sign != NULL) {
|
||
|
item = add_file_path(str, 1);
|
||
|
if (item) {
|
||
|
item->feature_type |= feature;
|
||
|
value = string_to_hex(r_sign + 1, INTEGRITY_LENGTH * 2, item->integrity);
|
||
|
if (!value)
|
||
|
return NULL;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
return item;
|
||
|
}
|
||
|
|
||
|
int store_tree(FILE *f, FILE *f_bin)
|
||
|
{
|
||
|
unsigned char *ptr = (unsigned char *)defex_packed_rules;
|
||
|
static char work_str[4096];
|
||
|
int i, offset = 0, index = 0;
|
||
|
|
||
|
if (packfiles_size)
|
||
|
defex_packed_rules->data_size = packfiles_size;
|
||
|
|
||
|
work_str[0] = 0;
|
||
|
fprintf(f, "#ifndef DEFEX_RAMDISK_ENABLE\n\n");
|
||
|
fprintf(f, "const unsigned char defex_packed_rules[] = {\n");
|
||
|
for (i = 0; i < packfiles_size; i++) {
|
||
|
if (index)
|
||
|
offset += snprintf(work_str + offset, sizeof(work_str) - offset, ", ");
|
||
|
offset += snprintf(work_str + offset, sizeof(work_str) - offset, "0x%02x", ptr[i]);
|
||
|
index++;
|
||
|
if (index == 16) {
|
||
|
fprintf(f, "\t%s,\n", work_str);
|
||
|
index = 0;
|
||
|
offset = 0;
|
||
|
}
|
||
|
}
|
||
|
if (index)
|
||
|
fprintf(f, "\t%s\n", work_str);
|
||
|
fprintf(f, "};\n");
|
||
|
fprintf(f, "\n#endif /* DEFEX_RAMDISK_ENABLE */\n\n");
|
||
|
fprintf(f, "#define DEFEX_RULES_ARRAY_SIZE\t\t%d\n", packfiles_size);
|
||
|
if (f_bin)
|
||
|
fwrite(defex_packed_rules, 1, packfiles_size, f_bin);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int remove_substr(char *str, const char *part)
|
||
|
{
|
||
|
int l, part_l, found = 0;
|
||
|
char *ptr;
|
||
|
|
||
|
l = strnlen(str, PATH_MAX - 1);
|
||
|
ptr = strstr(str, part);
|
||
|
if (ptr) {
|
||
|
part_l = strnlen(part, 32) - 1;
|
||
|
memmove(ptr, ptr + part_l, l - (ptr - str) - part_l + 1);
|
||
|
found = 1;
|
||
|
}
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
void trim_cr_lf(char *str)
|
||
|
{
|
||
|
char *ptr;
|
||
|
/* remove CR or LF at the end */
|
||
|
ptr = strchr(str, '\r');
|
||
|
if (ptr)
|
||
|
*ptr = 0;
|
||
|
ptr = strchr(str, '\n');
|
||
|
if (ptr)
|
||
|
*ptr = 0;
|
||
|
}
|
||
|
|
||
|
char* remove_redundant_chars(char *str)
|
||
|
{
|
||
|
int l;
|
||
|
|
||
|
/* skip hash values in the begin */
|
||
|
str += 65;
|
||
|
trim_cr_lf(str);
|
||
|
l = strnlen(str, PATH_MAX - 1);
|
||
|
/* remove starting dot or space */
|
||
|
while(l && (*str == '.' || *str == ' '))
|
||
|
str++;
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
int load_file_list(const char *name)
|
||
|
{
|
||
|
int found;
|
||
|
char *str;
|
||
|
FILE *lst_file = NULL;
|
||
|
struct file_list_item *file_list_new;
|
||
|
static char work_str[PATH_MAX*2];
|
||
|
|
||
|
lst_file = fopen(name, "r");
|
||
|
if (!lst_file)
|
||
|
return -1;
|
||
|
|
||
|
while(!feof(lst_file)) {
|
||
|
if (!fgets(work_str, sizeof(work_str), lst_file))
|
||
|
break;
|
||
|
str = remove_redundant_chars(work_str);
|
||
|
if (*str == '/' &&
|
||
|
(!strncmp(str, "/root/", 6) ||
|
||
|
!strncmp(str, "/product/", 9) ||
|
||
|
!strncmp(str, "/recovery/", 10) ||
|
||
|
!strncmp(str, "/system/", 8) ||
|
||
|
!strncmp(str, "/tmp/", 5) ||
|
||
|
!strncmp(str, "/vendor/", 8) ||
|
||
|
#if defined(DEFEX_FACTORY_ENABLE)
|
||
|
!strncmp(str, "/data/", 6) ||
|
||
|
#endif
|
||
|
!strncmp(str, "/apex/", 6) ||
|
||
|
!strncmp(str, "/system_ext/", 12))) {
|
||
|
remove_substr(str, "/root/");
|
||
|
found = remove_substr(str, "/recovery/");
|
||
|
file_list_count++;
|
||
|
file_list_new = realloc(file_list, sizeof(struct file_list_item) * file_list_count);
|
||
|
if (!file_list_new) {
|
||
|
free(file_list);
|
||
|
printf("WARNING: Can not allocate the filelist item!\n");
|
||
|
exit(-1);
|
||
|
}
|
||
|
file_list = file_list_new;
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
strncpy(file_list[file_list_count - 1].integrity, work_str, INTEGRITY_LENGTH * 2);
|
||
|
file_list[file_list_count - 1].integrity[INTEGRITY_LENGTH * 2] = 0;
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
SAFE_STRCOPY(file_list[file_list_count - 1].file_name, str);
|
||
|
file_list[file_list_count - 1].is_recovery = found;
|
||
|
}
|
||
|
}
|
||
|
fclose(lst_file);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int lookup_file_list(const char *rule, int for_recovery)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < file_list_count; i++) {
|
||
|
if (file_list[i].is_recovery == for_recovery
|
||
|
&& !strncmp(file_list[i].file_name, rule, strnlen(rule, PATH_MAX))
|
||
|
&& !strncmp(file_list[i].file_name, rule, strnlen(file_list[i].file_name, PATH_MAX)))
|
||
|
return i+1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifndef DEFEX_DEBUG_ENABLE
|
||
|
void process_debug_ifdef(const char *src_str)
|
||
|
{
|
||
|
char *ptr;
|
||
|
ptr = strstr(src_str, "#ifdef DEFEX_DEBUG_ENABLE");
|
||
|
if (ptr) {
|
||
|
while(ptr > src_str) {
|
||
|
ptr--;
|
||
|
if (*ptr != ' ' && *ptr != '\t')
|
||
|
return;
|
||
|
}
|
||
|
debug_ifdef_is_active = 1;
|
||
|
return;
|
||
|
}
|
||
|
ptr = strstr(src_str, "#endif");
|
||
|
if (ptr && debug_ifdef_is_active) {
|
||
|
while(ptr > src_str) {
|
||
|
ptr--;
|
||
|
if (*ptr != ' ' && *ptr != '\t')
|
||
|
return;
|
||
|
}
|
||
|
debug_ifdef_is_active = 0;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static int str_to_feature(const char *str)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < feature_match_size; i++) {
|
||
|
if (strstr(str, feature_match[i].feature_name)) {
|
||
|
return feature_match[i].feature_num;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int reduce_rules(const char *source_rules_file, const char *reduced_rules_file, const char *list_file)
|
||
|
{
|
||
|
int ret_val = -1;
|
||
|
int found_normal = 0, found_recovery = 0;
|
||
|
char *rule;
|
||
|
static char work_str[PATH_MAX*2], tmp_str[PATH_MAX*2];
|
||
|
FILE *src_file = NULL, *dst_file = NULL;
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
char *line_end, *integrity_normal;
|
||
|
char *integrity_recovery;
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
|
||
|
src_file = fopen(source_rules_file, "r");
|
||
|
if (!src_file)
|
||
|
return -1;
|
||
|
dst_file = fopen(reduced_rules_file, "wt");
|
||
|
if (!dst_file)
|
||
|
goto do_close2;
|
||
|
|
||
|
if (load_file_list(list_file) != 0)
|
||
|
goto do_close1;
|
||
|
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
memset(null_integrity, '0', sizeof(null_integrity) - 1);
|
||
|
null_integrity[sizeof(null_integrity) - 1] = 0;
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
|
||
|
while(!feof(src_file)) {
|
||
|
if (!fgets(work_str, sizeof(work_str), src_file))
|
||
|
break;
|
||
|
|
||
|
if (str_to_feature(work_str)) {
|
||
|
trim_cr_lf(work_str);
|
||
|
SAFE_STRCOPY(tmp_str, work_str);
|
||
|
rule = extract_rule_text(tmp_str);
|
||
|
found_normal = lookup_file_list(rule, 0);
|
||
|
found_recovery = lookup_file_list(rule, 1);
|
||
|
if (rule && !found_normal && !found_recovery && !strstr(work_str, "/* DEFAULT */")) {
|
||
|
printf("removed rule: %s\n", rule);
|
||
|
continue;
|
||
|
}
|
||
|
#ifdef DEFEX_INTEGRITY_ENABLE
|
||
|
integrity_normal = null_integrity;
|
||
|
integrity_recovery = null_integrity;
|
||
|
if (found_normal)
|
||
|
integrity_normal = file_list[found_normal - 1].integrity;
|
||
|
if (found_recovery)
|
||
|
integrity_recovery = file_list[found_recovery - 1].integrity;
|
||
|
|
||
|
line_end = strstr(work_str, "},");
|
||
|
if (line_end) {
|
||
|
*line_end = 0;
|
||
|
line_end += 2;
|
||
|
}
|
||
|
|
||
|
/* Add hash vale after each file path */
|
||
|
if (found_normal || (!found_normal && !found_recovery))
|
||
|
printf("remained rule: %s, %s %s\n",
|
||
|
rule, integrity_normal, (line_end != NULL)?line_end:"");
|
||
|
if (found_recovery)
|
||
|
printf("remained rule: %s, %s %s (R)\n",
|
||
|
rule, integrity_recovery, (line_end != NULL)?line_end:"");
|
||
|
|
||
|
fprintf(dst_file, "%s,\"", work_str);
|
||
|
if (found_normal)
|
||
|
fprintf(dst_file, "N%s", integrity_normal);
|
||
|
if (found_recovery)
|
||
|
fprintf(dst_file, "R%s", integrity_recovery);
|
||
|
|
||
|
fprintf(dst_file, "\"}, %s\n", (line_end != NULL)?line_end:"");
|
||
|
|
||
|
#else
|
||
|
printf("remained rule: %s\n", work_str);
|
||
|
fputs(work_str, dst_file);
|
||
|
fputs("\n", dst_file);
|
||
|
#endif /* DEFEX_INTEGRITY_ENABLE */
|
||
|
} else
|
||
|
fputs(work_str, dst_file);
|
||
|
}
|
||
|
ret_val = 0;
|
||
|
do_close1:
|
||
|
fclose(dst_file);
|
||
|
do_close2:
|
||
|
fclose(src_file);
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
int pack_rules(const char *source_rules_file, const char *packed_rules_file, const char *packed_rules_binfile)
|
||
|
{
|
||
|
int ret_val = -1;
|
||
|
int feature;
|
||
|
FILE *src_file = NULL, *dst_file = NULL, *dst_binfile = NULL;
|
||
|
static char work_str[PATH_MAX*2];
|
||
|
|
||
|
src_file = fopen(source_rules_file, "r");
|
||
|
if (!src_file)
|
||
|
return -1;
|
||
|
dst_file = fopen(packed_rules_file, "wt");
|
||
|
if (!dst_file)
|
||
|
goto do_close2;
|
||
|
if (packed_rules_binfile) {
|
||
|
dst_binfile = fopen(packed_rules_binfile, "wt");
|
||
|
if (!dst_binfile)
|
||
|
goto do_close3;
|
||
|
}
|
||
|
|
||
|
while(!feof(src_file)) {
|
||
|
if (!fgets(work_str, sizeof(work_str), src_file))
|
||
|
break;
|
||
|
#ifndef DEFEX_DEBUG_ENABLE
|
||
|
process_debug_ifdef(work_str);
|
||
|
if (!debug_ifdef_is_active) {
|
||
|
#endif
|
||
|
feature = str_to_feature(work_str);
|
||
|
if (feature) {
|
||
|
addline2tree(work_str, feature);
|
||
|
continue;
|
||
|
}
|
||
|
#ifndef DEFEX_DEBUG_ENABLE
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
store_tree(dst_file, dst_binfile);
|
||
|
if (!packfiles_count)
|
||
|
printf("WARNING: Defex packed rules tree is empty!\n");
|
||
|
ret_val = 0;
|
||
|
if (dst_binfile)
|
||
|
fclose(dst_binfile);
|
||
|
do_close3:
|
||
|
fclose(dst_file);
|
||
|
do_close2:
|
||
|
fclose(src_file);
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
static char param[4][PATH_MAX];
|
||
|
char *src_file = NULL, *packed_file = NULL, *packed_bin_file = NULL;
|
||
|
char *reduced_file = NULL, *list_file = NULL;
|
||
|
int i;
|
||
|
|
||
|
if (argc < 4 || argc > 5)
|
||
|
goto show_help;
|
||
|
|
||
|
for(i = 0; i < (argc - 2); i++) {
|
||
|
SAFE_STRCOPY(param[i], argv[i + 2]);
|
||
|
switch(i) {
|
||
|
case 0:
|
||
|
src_file = param[i];
|
||
|
break;
|
||
|
case 1:
|
||
|
packed_file = reduced_file = param[i];
|
||
|
break;
|
||
|
case 2:
|
||
|
packed_bin_file = list_file = param[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!strncmp(argv[1], "-p", 2)) {
|
||
|
if (pack_rules(src_file, packed_file, packed_bin_file) != 0)
|
||
|
goto show_help;
|
||
|
return 0;
|
||
|
|
||
|
} else if (!strncmp(argv[1], "-r", 2) && list_file) {
|
||
|
if (reduce_rules(src_file, reduced_file, list_file) != 0)
|
||
|
goto show_help;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
show_help:
|
||
|
printf("Defex rules processing utility.\nUSAGE:\n%s <CMD> <PARAMS>\n"
|
||
|
"Commands:\n"
|
||
|
" -p - Pack rules file to the tree. Params: <SOURCE_FILE> <PACKED_FILE> [PACKED_BIN_FILE]\n"
|
||
|
" -r - Reduce rules file (remove unexistent files). Params: <SOURCE_FILE> <REDUCED_FILE> <FILE_LIST>\n",
|
||
|
argv[0]);
|
||
|
return -1;
|
||
|
}
|