summaryrefslogtreecommitdiff
path: root/src/osfp.c
diff options
context:
space:
mode:
authorzhuzhenjun <[email protected]>2023-09-27 11:45:26 +0800
committerzhuzhenjun <[email protected]>2023-09-27 11:45:58 +0800
commit15d4a2d27198005b557b62dbfbb03c49d5b5220c (patch)
treefd93a8811d3f1453266c9568ae38c710e54d4cd0 /src/osfp.c
parenteeb4cc0b6bf9074765b5d3234238749aa63346f7 (diff)
v0.0.3
Diffstat (limited to 'src/osfp.c')
-rw-r--r--src/osfp.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/osfp.c b/src/osfp.c
new file mode 100644
index 0000000..1a847ec
--- /dev/null
+++ b/src/osfp.c
@@ -0,0 +1,258 @@
+#include "osfp_common.h"
+
+#include "osfp.h"
+#include "osfp_fingerprint.h"
+#include "osfp_score_db.h"
+#include "osfp_log.h"
+
+#define OSFP_DEFAULT_RESULT_BUFLEN_MAX 512
+
+static struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score)
+{
+ int i;
+ unsigned int tmp_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;
+
+ 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->detail.scores[i] = tmp_score;
+ }
+
+ result->likely_score = likely_score;
+ result->likely_os_class = likely_os_class;
+
+ if (likely_score < 10) {
+ result->likely_os_class = OSFP_OS_CLASS_OTHERS;
+ result->likely_score = 0;
+ } 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 && os_class_score->scores[i] == OSFP_OS_CLASS_ANDROID) {
+ continue;
+ } else if (likely_os_class == OSFP_OS_CLASS_MAC_OS && os_class_score->scores[i] == OSFP_OS_CLASS_IOS) {
+ continue;
+ } else {
+ result->likely_os_class = OSFP_OS_CLASS_UNKNOWN;
+ result->likely_score = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+exit:
+ return NULL;
+}
+
+const char *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 *osfp_result_score_detail_export(struct osfp_result *result)
+{
+ int i;
+ cJSON *root = NULL;
+ cJSON *array;
+ cJSON *os_score;
+
+ if (result == NULL) {
+ goto exit;
+ }
+
+ if (result->json_str != NULL) {
+ 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->likely_score);
+ }
+
+ array = cJSON_AddArrayToObject(root, "detail");
+ 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->detail.scores[i]);
+ cJSON_AddItemToArray(array, os_score);
+ }
+ }
+ }
+
+ result->json_str = malloc(OSFP_DEFAULT_RESULT_BUFLEN_MAX);
+ if (result->json_str == NULL) {
+ goto exit;
+ }
+
+ if (!cJSON_PrintPreallocated(root, result->json_str, OSFP_DEFAULT_RESULT_BUFLEN_MAX, 1)) {
+ goto exit;
+ }
+
+exit:
+ if (root) {
+ cJSON_Delete(root);
+ }
+ return result->json_str;
+}
+
+void osfp_result_free(struct osfp_result *result)
+{
+ if (result) {
+ if (result->json_str) {
+ free(result->json_str);
+ }
+ free(result);
+ }
+}
+
+struct osfp_result *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;
+
+ if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr == 0) {
+ goto exit;
+ }
+
+ ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 4);
+ 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 *osfp_ipv6_identify(struct osfp_db *db, struct ipv6hdr* 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) {
+ 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_db *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) {
+ osfp_db_free(db);
+ }
+ return NULL;
+}
+
+void 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);
+ }
+}