diff options
| author | zhuzhenjun <[email protected]> | 2023-10-12 15:05:58 +0800 |
|---|---|---|
| committer | zhuzhenjun <[email protected]> | 2023-10-12 15:36:31 +0800 |
| commit | 8b8627b0d8e06cb2d1073b2e86741dad8c39d4f6 (patch) | |
| tree | e41e8a5e70bc0d043f34b2a1651e026a15d54b4f /src/MESA_osfp.c | |
| parent | 7e1849233b8640e6139143c99423bf71cca0b6b2 (diff) | |
Diffstat (limited to 'src/MESA_osfp.c')
| -rw-r--r-- | src/MESA_osfp.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/MESA_osfp.c b/src/MESA_osfp.c new file mode 100644 index 0000000..f88cff8 --- /dev/null +++ b/src/MESA_osfp.c @@ -0,0 +1,318 @@ +#include "osfp_common.h" + +#include "MESA_osfp.h" +#include "osfp_fingerprint.h" +#include "osfp_score_db.h" +#include "osfp_log.h" + +#define OSFP_DEFAULT_RESULT_BUFLEN_MAX 512 +#define OSFP_LOWEST_SCORE_LIMIT 20 + +static struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score) +{ + int i; + unsigned int tmp_score; + unsigned int sum_score; + unsigned int likely_score; + enum osfp_os_class_id likely_os_class; + struct osfp_result *result; + + result = calloc(1, sizeof(struct osfp_result)); + if (result == NULL) { + goto exit; + } + + likely_score = 0; + likely_os_class = OSFP_OS_CLASS_OTHERS; + sum_score = 0; + + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + tmp_score = os_class_score->scores[i]; + + if (likely_score < tmp_score) { + likely_score = tmp_score; + likely_os_class = i; + } + result->details[i].score = tmp_score; + sum_score += tmp_score; + } + + if (sum_score) { + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + result->details[i].possibility = OSFP_PERCENTILE * result->details[i].score / sum_score; + } + } + + if (likely_score < OSFP_LOWEST_SCORE_LIMIT) { + likely_os_class = OSFP_OS_CLASS_OTHERS; + } else { + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + if (likely_os_class == i) { + continue; + } + if (likely_score == os_class_score->scores[i]) { + if (likely_os_class == OSFP_OS_CLASS_LINUX && i == OSFP_OS_CLASS_ANDROID) { + continue; + } else if (likely_os_class == OSFP_OS_CLASS_MAC_OS && i == OSFP_OS_CLASS_IOS) { + continue; + } else { + likely_os_class = OSFP_OS_CLASS_UNKNOWN; + break; + } + } + } + } + + result->likely_os_class = likely_os_class; + + return result; +exit: + return NULL; +} + +const char *MESA_osfp_result_os_name_get(struct osfp_result *result) +{ + enum osfp_os_class_id os_class; + + if (result == NULL) { + return NULL; + } + + os_class = result->likely_os_class; + if (os_class < 0 || os_class >= OSFP_OS_CLASS_MAX) { + return NULL; + } + + return osfp_os_class_id_to_name(os_class); +} + +char *MESA_osfp_result_score_detail_export(struct osfp_result *result) +{ + int i; + char *result_str = NULL; + cJSON *root = NULL; + cJSON *array; + cJSON *os_score; + + osfp_profile_cycle(c1); + osfp_profile_cycle(c2); + osfp_profile_get_cycle(c1); + + if (result == NULL) { + goto exit; + } + + if (result->json_str != NULL) { + result_str = result->json_str; + goto exit; + } + + root = cJSON_CreateObject(); + if (root == NULL) { + goto exit; + } + + os_score = cJSON_AddObjectToObject(root, "likely"); + if (os_score) { + cJSON_AddStringToObject(os_score, "name", osfp_os_class_id_to_name(result->likely_os_class)); + cJSON_AddNumberToObject(os_score, "score", result->details[result->likely_os_class].score); + //cJSON_AddNumberToObject(os_score, "possibility", result->details[result->likely_os_class].possibility); + } + + array = cJSON_AddArrayToObject(root, "details"); + if (array) { + for (i = OSFP_OS_CLASS_WINDOWS; i < OSFP_OS_CLASS_OTHERS; i++) { + os_score = cJSON_CreateObject(); + if (os_score) { + cJSON_AddStringToObject(os_score, "name", osfp_os_class_id_to_name(i)); + cJSON_AddNumberToObject(os_score, "score", result->details[i].score); + //cJSON_AddNumberToObject(os_score, "possibility", result->details[i].possibility); + cJSON_AddItemToArray(array, os_score); + } + } + } + + result_str = cJSON_Print(root); + if (result_str == NULL) { + goto exit; + } + + result->json_str = result_str; + +exit: + if (root) { + cJSON_Delete(root); + } + if (result_str) { + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_result_export, c2 - c1); + } + return result_str; +} + +void MESA_osfp_result_free(struct osfp_result *result) +{ + if (result) { + if (result->json_str) { + free(result->json_str); + } + free(result); + } +} + +struct osfp_result *MESA_osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len) +{ + int ret = OSFP_EINVAL; + struct osfp_fingerprint fp; + struct osfp_os_class_score os_class_score; + struct osfp_result *result; + + osfp_profile_cycle(c1); + osfp_profile_cycle(c2); + + if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr == 0) { + goto exit; + } + + osfp_profile_get_cycle(c1); + ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 4); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_fingerprinting, c2 - c1); + if (ret != 0) { + goto exit; + } + + osfp_profile_get_cycle(c1); + ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_score, c2 - c1); + if (ret != 0) { + goto exit; + } + + osfp_profile_get_cycle(c1); + result = osfp_result_build(&os_class_score); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1); + if (result == NULL) { + goto exit; + } + + return result; +exit: + return NULL; +} + +struct osfp_result *MESA_osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len) +{ + int ret = OSFP_EINVAL; + struct osfp_fingerprint fp; + struct osfp_os_class_score os_class_score; + struct osfp_result *result; + + if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 0) { + goto exit; + } + + ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 6); + if (ret != 0) { + goto exit; + } + + ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); + if (ret != 0) { + goto exit; + } + + result = osfp_result_build(&os_class_score); + if (result == NULL) { + goto exit; + } + + return result; +exit: + return NULL; +} + +struct osfp_result *MESA_osfp_json_identify(struct osfp_db *db, const char *json_str) +{ + int ret = OSFP_EINVAL; + struct osfp_fingerprint fp; + struct osfp_os_class_score os_class_score; + struct osfp_result *result; + + if (db == NULL) { + goto exit; + } + + ret = osfp_fingerprint_from_json(&fp, (char *)json_str); + if (ret != 0) { + goto exit; + } + + ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); + if (ret != 0) { + goto exit; + } + + result = osfp_result_build(&os_class_score); + if (result == NULL) { + goto exit; + } + + return result; +exit: + return NULL; +} + +struct osfp_db *MESA_osfp_db_new(const char *db_json_file) +{ + int ret; + struct osfp_db *db; + + db = calloc(1, sizeof(struct osfp_db)); + if (db == NULL) { + goto exit; + } + + if (db_json_file != NULL) { + if (0 != access(db_json_file, R_OK)) { + goto exit; + } + + db->db_json_path = strdup((const char*)db_json_file); + if (db->db_json_path == NULL) { + goto exit; + } + } + + db->score_db = (void *)osfp_score_db_create(); + if (db->score_db == NULL) { + goto exit; + } + + ret = osfp_score_db_load((struct osfp_score_db *)db->score_db, db->db_json_path); + if (ret != 0) { + goto exit; + } + + return db; +exit: + if (db) { + MESA_osfp_db_free(db); + } + return NULL; +} + +void MESA_osfp_db_free(struct osfp_db *db) +{ + if (db) { + if (db->db_json_path) { + free(db->db_json_path); + } + if (db->score_db) { + osfp_score_db_destroy(db->score_db); + } + free(db); + } +} |
