This commit is contained in:
zhuzhenjun
2023-09-22 15:59:40 +08:00
parent 91e6b79afc
commit 554867aa4e
16 changed files with 73081 additions and 344 deletions

View File

@@ -9,10 +9,16 @@ libosfp_la_SOURCES = \
utstring.h \
cJSON.h \
cJSON.c \
libosfp_common.h \
libosfp_common.c \
libosfp_default_fingerprints.h \
libosfp_default_fingerprints.c \
libosfp.h \
libosfp.c \
libosfp_fingerprint.h \
libosfp_fingerprint.c \
libosfp_log.h \
libosfp_log.c \
libosfp_score_db.h \
libosfp_score_db.c

View File

@@ -1,77 +1,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include "libosfp.h"
#include "libosfp_fingerprint.h"
#include "libosfp_score_db.h"
#include "libosfp_log.h"
#define LIBOSFP_OS_CLASS_NAME_WINDOWS "Windows"
#define LIBOSFP_OS_CLASS_NAME_LINUX "Linux"
#define LIBOSFP_OS_CLASS_NAME_MAC_OS "Mac OS"
#define LIBOSFP_OS_CLASS_NAME_IOS "iOS"
#define LIBOSFP_OS_CLASS_NAME_ANDROID "Android"
#define LIBOSFP_WRITE_STRING_TO_BUF(ret, buf, size, off, ...) do { \
ret = snprintf((char *)buf + off, \
size - off, \
__VA_ARGS__); \
if (ret >= 0) { \
if ( (off + ret) >= size) { \
off = size - 1; \
} else { \
off += ret; \
} \
} \
} while (0)
const char *os_class_name[LIBOSFP_OS_CLASS_MAX] = {
LIBOSFP_OS_CLASS_NAME_WINDOWS,
LIBOSFP_OS_CLASS_NAME_LINUX,
LIBOSFP_OS_CLASS_NAME_MAC_OS,
LIBOSFP_OS_CLASS_NAME_IOS,
LIBOSFP_OS_CLASS_NAME_ANDROID
};
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name)
{
libosfp_os_class_id_t os_class;
if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_WINDOWS, strlen(LIBOSFP_OS_CLASS_NAME_WINDOWS))) {
os_class = LIBOSFP_OS_CLASS_WINDOWS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_LINUX, strlen(LIBOSFP_OS_CLASS_NAME_LINUX))) {
os_class = LIBOSFP_OS_CLASS_Linux;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_MAC_OS, strlen(LIBOSFP_OS_CLASS_NAME_MAC_OS))) {
os_class = LIBOSFP_OS_CLASS_MAC_OS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_IOS, strlen(LIBOSFP_OS_CLASS_NAME_IOS))) {
os_class = LIBOSFP_OS_CLASS_IOS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_ANDROID, strlen(LIBOSFP_OS_CLASS_NAME_ANDROID))) {
os_class = LIBOSFP_OS_CLASS_ANDROID;
} else {
os_class = LIBOSFP_OS_CLASS_MAX;
}
return os_class;
}
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class)
{
if (os_class < 0 || os_class >= LIBOSFP_OS_CLASS_MAX) {
return NULL;
}
return os_class_name[os_class];
}
const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result)
{
libosfp_os_class_id_t os_class;
@@ -80,50 +11,45 @@ const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result)
return NULL;
}
os_class = result->likely_os_class;
os_class = result->score.likely_os_class;
if (os_class < 0 || os_class >= LIBOSFP_OS_CLASS_MAX) {
return NULL;
}
return os_class_name[os_class];
}
unsigned int libosfp_result_likely_os_class_score_get(libosfp_result_t *result)
{
if (result == NULL) {
return 0;
}
return result->likely_score;
return libosfp_os_class_id_to_name(os_class);
}
int libosfp_result_to_buf(libosfp_result_t *result, char *strbuf, unsigned int buf_len)
{
int ret, offset = 0, i;
libosfp_os_class_id_t likely_os_class;
if (result == NULL || strbuf == NULL || buf_len == 0) {
return 0;
}
likely_os_class = result->score.likely_os_class;
if (likely_os_class < 0 || likely_os_class >= LIBOSFP_OS_CLASS_MAX) {
return 0;
}
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,
"Most likely os class: %s\nLikely score: %u/100\n",
os_class_name[result->likely_os_class], result->likely_score);
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,"Details:\n");
libosfp_os_class_id_to_name(likely_os_class), result->score.likely_score);
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,"%s score: %u\n",
os_class_name[i], result->score.os_class_score[i]);
libosfp_os_class_id_to_name(i), result->score.os_class_score[i]);
}
exit:
return offset;
}
libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result)
libosfp_error_code_t libosfp_detect(libosfp_context_t *libosfp_context, unsigned int flags, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result)
{
int ret = LIBOSFP_EINVAL;
libosfp_fingerprint_t fp = {0};
libosfp_fingerprint_t fp;
if (libosfp_context == NULL || ip_hdr == NULL || tcp_hdr == NULL || result == NULL) {
goto exit;
@@ -134,7 +60,7 @@ libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, un
goto exit;
}
ret = libosfp_score_db_score(libosfp_context, &fp, result);
ret = libosfp_score_db_score(libosfp_context->score_db, flags, &fp, &result->score);
if (ret != 0) {
goto exit;
}
@@ -164,20 +90,22 @@ exit:
libosfp_context_t *libosfp_context_create(char *fp_file)
{
libosfp_context_t *libosfp_context = NULL;
libosfp_context_t *libosfp_context;
if (fp_file == NULL || 0 != access(fp_file, R_OK)) {
goto exit;
}
libosfp_context = malloc(sizeof(libosfp_context_t));
libosfp_context = calloc(1, sizeof(libosfp_context_t));
if (libosfp_context == NULL) {
goto exit;
}
libosfp_context->fp_file = strdup((const char*)fp_file);
if (libosfp_context->fp_file == NULL) {
goto exit;
if (fp_file != NULL) {
if (0 != access(fp_file, R_OK)) {
goto exit;
}
libosfp_context->fp_file = strdup((const char*)fp_file);
if (libosfp_context->fp_file == NULL) {
goto exit;
}
}
libosfp_context->score_db = (void *)libosfp_score_db_create();

View File

@@ -1,32 +1,10 @@
#ifndef __LIBOSFP_H__
#define __LIBOSFP_H__
typedef enum libosfp_error_code {
LIBOSFP_NOERR,
LIBOSFP_EINVAL,
LIBOSFP_ERR_READ_FILE,
LIBOSFP_ERR_PARSE_FILE,
} libosfp_error_code_t;
typedef enum libosfp_os_class_id {
LIBOSFP_OS_CLASS_WINDOWS,
LIBOSFP_OS_CLASS_Linux,
LIBOSFP_OS_CLASS_MAC_OS,
LIBOSFP_OS_CLASS_IOS,
LIBOSFP_OS_CLASS_ANDROID,
LIBOSFP_OS_CLASS_MAX,
} libosfp_os_class_id_t;
typedef struct libosfp_score {
unsigned int os_class_score[LIBOSFP_OS_CLASS_MAX];
} libosfp_score_t;
#include "libosfp_common.h"
typedef struct libosfp_result {
enum libosfp_error_code err;
enum libosfp_os_class_id likely_os_class; // top rated os class
unsigned int likely_score;
unsigned int perfect_score;
libosfp_score_t score;
libosfp_score_t score;
} libosfp_result_t;
typedef struct libosfp_context {
@@ -34,15 +12,10 @@ typedef struct libosfp_context {
void *score_db;
} libosfp_context_t;
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name);
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class);
int libosfp_result_to_buf(libosfp_result_t *result, char *strbuf, unsigned int buf_len);
unsigned int libosfp_result_likely_os_class_score_get(libosfp_result_t *result);
const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result);
libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result);
libosfp_error_code_t libosfp_detect(libosfp_context_t *libosfp_context, unsigned int flags, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result);
libosfp_error_code_t libosfp_context_setup(libosfp_context_t *libosfp_context);
libosfp_context_t *libosfp_context_create(char *fp_file);
void libosfp_context_destroy(libosfp_context_t *libosfp_context);

36
src/libosfp_common.c Normal file
View File

@@ -0,0 +1,36 @@
#include "libosfp_common.h"
const char *os_class_name[LIBOSFP_OS_CLASS_MAX] = {
LIBOSFP_OS_CLASS_NAME_WINDOWS,
LIBOSFP_OS_CLASS_NAME_LINUX,
LIBOSFP_OS_CLASS_NAME_MAC_OS,
LIBOSFP_OS_CLASS_NAME_IOS,
LIBOSFP_OS_CLASS_NAME_ANDROID
};
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name)
{
libosfp_os_class_id_t os_class;
if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_WINDOWS, strlen(LIBOSFP_OS_CLASS_NAME_WINDOWS))) {
os_class = LIBOSFP_OS_CLASS_WINDOWS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_LINUX, strlen(LIBOSFP_OS_CLASS_NAME_LINUX))) {
os_class = LIBOSFP_OS_CLASS_LINUX;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_MAC_OS, strlen(LIBOSFP_OS_CLASS_NAME_MAC_OS))) {
os_class = LIBOSFP_OS_CLASS_MAC_OS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_IOS, strlen(LIBOSFP_OS_CLASS_NAME_IOS))) {
os_class = LIBOSFP_OS_CLASS_IOS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_ANDROID, strlen(LIBOSFP_OS_CLASS_NAME_ANDROID))) {
os_class = LIBOSFP_OS_CLASS_ANDROID;
} else {
os_class = LIBOSFP_OS_CLASS_MAX;
}
return os_class;
}
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class)
{
return os_class_name[os_class];
}

142
src/libosfp_common.h Normal file
View File

@@ -0,0 +1,142 @@
#ifndef __LIBOSFP_COMMON_H__
#define __LIBOSFP_COMMON_H__
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <stdarg.h>
#include <time.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "utarray.h"
#include "uthash.h"
#include "utlist.h"
#include "utringbuffer.h"
#include "utstack.h"
#include "utstring.h"
#include "cJSON.h"
#define LIBOSFP_OS_CLASS_NAME_WINDOWS "Windows"
#define LIBOSFP_OS_CLASS_NAME_LINUX "Linux"
#define LIBOSFP_OS_CLASS_NAME_MAC_OS "Mac OS"
#define LIBOSFP_OS_CLASS_NAME_IOS "iOS"
#define LIBOSFP_OS_CLASS_NAME_ANDROID "Android"
#define LIBOSFP_TCP_OPTLENMAX 64
#define LIBOSFP_TCP_OPTMAX 20
#define LIBOSFP_ETHERNET_HEADER_LEN 14
#define LIBOSFP_VLAN_HEADER_LEN 4
#define LIBOSFP_IPV4_HEADER_LEN 20
#define LIBOSFP_IPV6_HEADER_LEN 40
#define LIBOSFP_TCP_HEADER_LEN 20
//# TCP Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
#define LIBOSFP_TCP_OPT_EOL 0 //# end of option list
#define LIBOSFP_TCP_OPT_NOP 1 //# no operation
#define LIBOSFP_TCP_OPT_MSS 2 //# maximum segment size
#define LIBOSFP_TCP_OPT_WSCALE 3 //# window scale factor, RFC 1072
#define LIBOSFP_TCP_OPT_SACKOK 4 //# SACK permitted, RFC 2018
#define LIBOSFP_TCP_OPT_SACK 5 //# SACK, RFC 2018
#define LIBOSFP_TCP_OPT_ECHO 6 //# echo (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_ECHOREPLY 7 //# echo reply (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_TIMESTAMP 8 //# timestamps, RFC 1323
#define LIBOSFP_TCP_OPT_POCONN 9 //# partial order conn, RFC 1693
#define LIBOSFP_TCP_OPT_POSVC 10 //# partial order service, RFC 1693
#define LIBOSFP_TCP_OPT_CC 11 //# connection count, RFC 1644
#define LIBOSFP_TCP_OPT_CCNEW 12 //# CC.NEW, RFC 1644
#define LIBOSFP_TCP_OPT_CCECHO 13 //# CC.ECHO, RFC 1644
#define LIBOSFP_TCP_OPT_ALTSUM 14 //# alt checksum request, RFC 1146
#define LIBOSFP_TCP_OPT_ALTSUMDATA 15 //# alt checksum data, RFC 1146
#define LIBOSFP_TCP_OPT_SKEETER 16 //# Skeeter
#define LIBOSFP_TCP_OPT_BUBBA 17 //# Bubba
#define LIBOSFP_TCP_OPT_TRAILSUM 18 //# trailer checksum
#define LIBOSFP_TCP_OPT_MD5 19 //# MD5 signature, RFC 2385
#define LIBOSFP_TCP_OPT_SCPS 20 //# SCPS capabilities
#define LIBOSFP_TCP_OPT_SNACK 21 //# selective negative acks
#define LIBOSFP_TCP_OPT_REC 22 //# record boundaries
#define LIBOSFP_TCP_OPT_CORRUPT 23 //# corruption experienced
#define LIBOSFP_TCP_OPT_SNAP 24 //# SNAP
#define LIBOSFP_TCP_OPT_TCPCOMP 26 //# TCP compression filter
#define LIBOSFP_TCP_OPT_MAX 27 //# Quick-Start Response
#define LIBOSFP_TCP_OPT_USRTO 28 //# User Timeout Option (also, other known unauthorized use) [***][1] [RFC5482]
#define LIBOSFP_TCP_OPT_AUTH 29 //# TCP Authentication Option (TCP-AO) [RFC5925]
#define LIBOSFP_TCP_OPT_MULTIPATH 30 //# Multipath TCP (MPTCP)
#define LIBOSFP_TCP_OPT_FASTOPEN 34 //# TCP Fast Open Cookie [RFC7413]
#define LIBOSFP_TCP_OPY_ENCNEG 69 //# Encryption Negotiation (TCP-ENO) [RFC8547]
#define LIBOSFP_TCP_OPT_EXP1 253 //# RFC3692-style Experiment 1 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_EXP2 254 //# RFC3692-style Experiment 2 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_SACKOK_LEN 2
#define LIBOSFP_TCP_OPT_WS_LEN 3
#define LIBOSFP_TCP_OPT_TS_LEN 10
#define LIBOSFP_TCP_OPT_MSS_LEN 4
#define LIBOSFP_TCP_OPT_SACK_MIN_LEN 10 /* hdr 2, 1 pair 8 = 10 */
#define LIBOSFP_TCP_OPT_SACK_MAX_LEN 34 /* hdr 2, 4 pair 32= 34 */
#define LIBOSFP_TCP_OPT_TFO_MIN_LEN 4 /* kind, len, 2 bytes cookie: 4 */
#define LIBOSFP_TCP_OPT_TFO_MAX_LEN 18 /* kind, len, 18 */
#define LIBOSFP_WRITE_STRING_TO_BUF(ret, buf, size, off, ...) do { \
ret = snprintf((char *)buf + off, \
size - off, \
__VA_ARGS__); \
if (ret >= 0) { \
if ( (off + ret) >= size) { \
off = size - 1; \
} else { \
off += ret; \
} \
} \
} while (0)
#define LIBOSFP_BIT_U32(n) (1UL << (n))
typedef enum libosfp_error_code {
LIBOSFP_NOERR,
LIBOSFP_EINVAL,
LIBOSFP_ENOMEM,
LIBOSFP_ERR_SCORE_DB_READ_FILE,
LIBOSFP_ERR_SCORE_DB_PARSE_FILE,
LIBOSFP_ERR_SCORE_DB_UNSUPPORTED,
LIBOSFP_ERR_FINGERPRINTING_UNSUPPORTED,
} libosfp_error_code_t;
typedef enum libosfp_os_class_id {
LIBOSFP_OS_CLASS_WINDOWS,
LIBOSFP_OS_CLASS_LINUX,
LIBOSFP_OS_CLASS_MAC_OS,
LIBOSFP_OS_CLASS_IOS,
LIBOSFP_OS_CLASS_ANDROID,
LIBOSFP_OS_CLASS_MAX,
} libosfp_os_class_id_t;
#define LIBOSFP_OS_CLASS_FLAG_WINDOWS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_WINDOWS)
#define LIBOSFP_OS_CLASS_FLAG_LINUX LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_LINUX)
#define LIBOSFP_OS_CLASS_FLAG_MAC_OS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_MAC_OS)
#define LIBOSFP_OS_CLASS_FLAG_IOS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_IOS)
#define LIBOSFP_OS_CLASS_FLAG_ANDROID LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_ANDROID)
typedef struct libosfp_score {
unsigned int likely_os_class;
unsigned int likely_score;
unsigned int os_class_score[LIBOSFP_OS_CLASS_MAX];
} libosfp_score_t;
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name);
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class);
#endif

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
// File generated by gen_c.sh
#ifndef _LIBOSFP_DEFAULT_FINGERPRINTS_H__
#define _LIBOSFP_DEFAULT_FINGERPRINTS_H__
extern const char *g_default_fingerprints;
#endif

View File

@@ -1,25 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include "cJSON.h"
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_fingerprint.h"
#include "libosfp_log.h"
#define LIBOSFP_ETHERNET_HEADER_LEN 14
#define LIBOSFP_VLAN_HEADER_LEN 4
#define LIBOSFP_IPV4_HEADER_LEN 20
#define LIBOSFP_IPV6_HEADER_LEN 40
#define LIBOSFP_TCP_HEADER_LEN 20
#define LIBOSFP_FINGERPRINT_FIELD_NAME_IP_ID "ip_id"
#define LIBOSFP_FINGERPRINT_FIELD_NAME_IP_TOS "ip_tos"
@@ -36,6 +18,7 @@
#define LIBOSFP_FINGERPRINT_FIELD_NAME_TCP_OPTIONS_ORDERED "tcp_options_ordered"
#define LIBOSFP_FINGERPRINT_FIELD_NAME_OS "os"
#define LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME "LIBOSFP_UNKNOWN"
typedef struct libosfp_tcp_opt {
unsigned char type;
@@ -98,7 +81,7 @@ static unsigned int compute_ip_ttl(unsigned int ip_ttl)
ip_ttl = 64;
} else if (ip_ttl > 64 && ip_ttl <= 128) {
ip_ttl = 128;
} else if (ip_ttl > 128) {
} else {
ip_ttl = 255;
}
return ip_ttl;
@@ -109,11 +92,11 @@ static unsigned int decode_tcp_options(libosfp_tcp_opt_t *tcp_opts, unsigned int
unsigned int offset = 0;
unsigned int tcp_opt_cnt = 0;
while (offset < len && tcp_opt_cnt < max_opt_cnt) {
unsigned char type;
unsigned char olen;
unsigned char *odata;
unsigned char type;
unsigned char olen;
unsigned char *odata;
while (offset < len && tcp_opt_cnt < max_opt_cnt) {
type = *(data + offset);
if (type == LIBOSFP_TCP_OPT_EOL || type == LIBOSFP_TCP_OPT_NOP) {
@@ -217,15 +200,9 @@ void libosfp_fingerprint_setup_field(libosfp_fingerprint_t *fp, libosfp_field_id
}
}
void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen, libosfp_fingerprint_t *fp)
void libosfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int opt_len, libosfp_fingerprint_t *fp)
{
int ret,i;
char options[LIBOSFP_TCP_OPTLENMAX];
char options_ordered[LIBOSFP_TCP_OPTLENMAX];
unsigned int maxoffset = sizeof(options) - 3;
unsigned int ordered_maxoffset = sizeof(options_ordered) - 1;
unsigned int offset = 0;
unsigned int ordered_offset = 0;
unsigned int tcp_mss;
unsigned int tcp_ws;
@@ -233,7 +210,14 @@ void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen,
unsigned int tcp_opt_cnt;
libosfp_tcp_opt_t tcp_opts[LIBOSFP_TCP_OPTMAX];
tcp_opt_cnt = decode_tcp_options(tcp_opts, LIBOSFP_TCP_OPTMAX, pkt, pktlen);
char options[LIBOSFP_TCP_OPTLENMAX];
char options_ordered[LIBOSFP_TCP_OPTLENMAX];
unsigned int offset = 0;
unsigned int maxoffset = sizeof(options) - 3; //for shortest "E,"
unsigned int ordered_offset = 0;
unsigned int ordered_maxoffset = sizeof(options_ordered) - 1;
tcp_opt_cnt = decode_tcp_options(tcp_opts, LIBOSFP_TCP_OPTMAX, opt_data, opt_len);
for (i = 0; i < tcp_opt_cnt && offset < maxoffset && ordered_offset < ordered_maxoffset; i++) {
libosfp_tcp_opt_t *opt = &tcp_opts[i];
@@ -324,7 +308,7 @@ int libosfp_fingerprinting_tcp(struct tcphdr *tcph, libosfp_fingerprint_t *fp)
// tcp options
if (tcp_off > LIBOSFP_TCP_HEADER_LEN) {
libosfp_fingerprinting_tcp_option((unsigned char *)tcph + LIBOSFP_TCP_HEADER_LEN, tcp_off - LIBOSFP_TCP_HEADER_LEN, fp);
libosfp_fingerprinting_tcp_option((unsigned char *)tcph + LIBOSFP_TCP_HEADER_LEN, 20 + tcp_off - LIBOSFP_TCP_HEADER_LEN, fp);
}
return 0;
@@ -376,7 +360,8 @@ exit:
int libosfp_fingerprinting(unsigned char *iph, unsigned char *tcph, libosfp_fingerprint_t *fp)
{
int ret, ip_version;
int ret = LIBOSFP_EINVAL;
int ip_version;
if (iph == NULL || tcph == NULL || fp == NULL) {
goto exit;
@@ -407,7 +392,7 @@ int libosfp_fingerprinting(unsigned char *iph, unsigned char *tcph, libosfp_fing
goto exit;
}
libosfp_fingerprint_setup_field(fp, LIBOSFP_FIELD_OS, "", strlen("") + 1);
libosfp_fingerprint_setup_field(fp, LIBOSFP_FIELD_OS, LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME, strlen(LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME) + 1);
return 0;
exit:

View File

@@ -1,59 +1,8 @@
#ifndef __LIBOSFP_FINGERPRINT_H__
#define __LIBOSFP_FINGERPRINT_H__
#include "libosfp.h"
#define LIBOSFP_FINGERPRINT_VALUE_BUFFER_MAX 128
#define LIBOSFP_TCP_OPTLENMAX 64
#define LIBOSFP_TCP_OPTMAX 20
//# TCP Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
#define LIBOSFP_TCP_OPT_EOL 0 //# end of option list
#define LIBOSFP_TCP_OPT_NOP 1 //# no operation
#define LIBOSFP_TCP_OPT_MSS 2 //# maximum segment size
#define LIBOSFP_TCP_OPT_WSCALE 3 //# window scale factor, RFC 1072
#define LIBOSFP_TCP_OPT_SACKOK 4 //# SACK permitted, RFC 2018
#define LIBOSFP_TCP_OPT_SACK 5 //# SACK, RFC 2018
#define LIBOSFP_TCP_OPT_ECHO 6 //# echo (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_ECHOREPLY 7 //# echo reply (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_TIMESTAMP 8 //# timestamps, RFC 1323
#define LIBOSFP_TCP_OPT_POCONN 9 //# partial order conn, RFC 1693
#define LIBOSFP_TCP_OPT_POSVC 10 //# partial order service, RFC 1693
#define LIBOSFP_TCP_OPT_CC 11 //# connection count, RFC 1644
#define LIBOSFP_TCP_OPT_CCNEW 12 //# CC.NEW, RFC 1644
#define LIBOSFP_TCP_OPT_CCECHO 13 //# CC.ECHO, RFC 1644
#define LIBOSFP_TCP_OPT_ALTSUM 14 //# alt checksum request, RFC 1146
#define LIBOSFP_TCP_OPT_ALTSUMDATA 15 //# alt checksum data, RFC 1146
#define LIBOSFP_TCP_OPT_SKEETER 16 //# Skeeter
#define LIBOSFP_TCP_OPT_BUBBA 17 //# Bubba
#define LIBOSFP_TCP_OPT_TRAILSUM 18 //# trailer checksum
#define LIBOSFP_TCP_OPT_MD5 19 //# MD5 signature, RFC 2385
#define LIBOSFP_TCP_OPT_SCPS 20 //# SCPS capabilities
#define LIBOSFP_TCP_OPT_SNACK 21 //# selective negative acks
#define LIBOSFP_TCP_OPT_REC 22 //# record boundaries
#define LIBOSFP_TCP_OPT_CORRUPT 23 //# corruption experienced
#define LIBOSFP_TCP_OPT_SNAP 24 //# SNAP
#define LIBOSFP_TCP_OPT_TCPCOMP 26 //# TCP compression filter
#define LIBOSFP_TCP_OPT_MAX 27 //# Quick-Start Response
#define LIBOSFP_TCP_OPT_USRTO 28 //# User Timeout Option (also, other known unauthorized use) [***][1] [RFC5482]
#define LIBOSFP_TCP_OPT_AUTH 29 //# TCP Authentication Option (TCP-AO) [RFC5925]
#define LIBOSFP_TCP_OPT_MULTIPATH 30 //# Multipath TCP (MPTCP)
#define LIBOSFP_TCP_OPT_FASTOPEN 34 //# TCP Fast Open Cookie [RFC7413]
#define LIBOSFP_TCP_OPY_ENCNEG 69 //# Encryption Negotiation (TCP-ENO) [RFC8547]
#define LIBOSFP_TCP_OPT_EXP1 253 //# RFC3692-style Experiment 1 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_EXP2 254 //# RFC3692-style Experiment 2 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_SACKOK_LEN 2
#define LIBOSFP_TCP_OPT_WS_LEN 3
#define LIBOSFP_TCP_OPT_TS_LEN 10
#define LIBOSFP_TCP_OPT_MSS_LEN 4
#define LIBOSFP_TCP_OPT_SACK_MIN_LEN 10 /* hdr 2, 1 pair 8 = 10 */
#define LIBOSFP_TCP_OPT_SACK_MAX_LEN 34 /* hdr 2, 4 pair 32= 34 */
#define LIBOSFP_TCP_OPT_TFO_MIN_LEN 4 /* kind, len, 2 bytes cookie: 4 */
#define LIBOSFP_TCP_OPT_TFO_MAX_LEN 18 /* kind, len, 18 */
typedef enum libosfp_field_id {
LIBOSFP_FIELD_IP_ID,
LIBOSFP_FIELD_IP_TOS,
@@ -99,8 +48,13 @@ char *libosfp_fingerprint_get_field_name(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_enabled(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_importance(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_type(libosfp_field_id_t field_id);
int libosfp_fingerprint_to_json_buf(libosfp_fingerprint_t *fp, char *strbuf, unsigned int buf_len);
void libosfp_fingerprint_setup_field(libosfp_fingerprint_t *fp, libosfp_field_id_t field_id, void *value, unsigned int len);
void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_tcp(struct tcphdr *tcph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_ipv4(struct iphdr *iph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_ipv6(struct ipv6hdr *iph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting(unsigned char *iphdr, unsigned char *tcphdr, libosfp_fingerprint_t *fp);
#endif

View File

@@ -1,9 +1,4 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_log.h"
/* The maximum length of the log message */
@@ -24,22 +19,22 @@ void libosfp_log_message(unsigned int x, const char *file, const int line, const
switch (x) {
case LIBOSFP_LOG_LEVEL_DEBUG:
snprintf(buffer, sizeof(buffer), "[%s][DEBUG][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][DEBUG][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_INFO:
snprintf(buffer, sizeof(buffer), "[%s][INFO][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][INFO][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_WARNING:
snprintf(buffer, sizeof(buffer), "[%s][WARN][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][WARN][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_ERROR:
snprintf(buffer, sizeof(buffer), "[%s][ERROR][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][ERROR][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
}
}
void libosfp_log(unsigned int x, const char *file, const char *func, const int line, const char *fmt, ...)
void libosfp_log(unsigned int x, const char *file, const int line, const char *func, const char *fmt, ...)
{
if (libosfp_log_level >= x ) {
char msg[LIBOSFP_MAX_LOG_MSG_LEN];

View File

@@ -8,13 +8,17 @@ typedef enum libosfp_log_level {
LIBOSFP_LOG_LEVEL_ERROR
} libosfp_log_level_t;
#ifndef DEBUG
#define libosfp_log_debug(...) do { } while (0)
#else
#define libosfp_log_debug(...) libosfp_log(LIBOSFP_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#endif
#define libosfp_log_info(...) libosfp_log(LIBOSFP_LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define libosfp_log_warning(...) libosfp_log(LIBOSFP_LOG_LEVEL_WARNING, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define libosfp_log_error(...) libosfp_log(LIBOSFP_LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__,__VA_ARGS__)
void libosfp_log_level_set(libosfp_log_level_t level);
void libosfp_log(unsigned int x, const char *file, const char *func, const int line, const char *fmt, ...);
void libosfp_log(unsigned int x, const char *file, const int line, const char *func, const char *fmt, ...);
#endif

View File

@@ -1,26 +1,12 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include "libosfp_common.h"
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "uthash.h"
#include "cJSON.h"
#include "libosfp.h"
#include "libosfp_fingerprint.h"
#include "libosfp_default_fingerprints.h"
#include "libosfp_score_db.h"
#include "libosfp_log.h"
#define LIBOSFP_PERCENTILE 100
#define LIBOSFP_SCORE_DB_FIELD_UINT_VALUE_MAX 65536
typedef struct libosfp_score_db_array_data {
@@ -353,25 +339,34 @@ exit:
int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
{
int ret = LIBOSFP_EINVAL, i;
char *file_buffer;
const char *file_buffer;
libosfp_field_score_db_t *field_score_db;
cJSON *root = NULL;
cJSON *entry = NULL;
if (score_db == NULL || fp_file == NULL) {
if (score_db == NULL) {
goto exit;
}
file_buffer = libosfp_score_db_read_file(fp_file);
if (file_buffer == NULL) {
ret = LIBOSFP_ERR_READ_FILE;
goto exit;
if (fp_file == NULL) {
file_buffer = g_default_fingerprints;
} else {
file_buffer = (const char *)libosfp_score_db_read_file(fp_file);
if (file_buffer == NULL) {
ret = LIBOSFP_ERR_SCORE_DB_READ_FILE;
goto exit;
}
}
root = cJSON_Parse(file_buffer);
if (file_buffer != g_default_fingerprints) {
free((char*)file_buffer);
}
if (root == NULL) {
ret = LIBOSFP_ERR_PARSE_FILE;
ret = LIBOSFP_ERR_SCORE_DB_PARSE_FILE;
goto exit;
}
@@ -389,7 +384,7 @@ int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
if (entry) {
ret = libosfp_score_db_load_entry(score_db, entry);
if (ret != 0) {
printf("json entry load failed.\n%s\n", cJSON_Print(entry));
libosfp_log_debug("json entry load failed.\n%s\n", cJSON_Print(entry));
continue;
}
}
@@ -397,54 +392,58 @@ int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
cJSON_Delete(root);
return 0;
return LIBOSFP_NOERR;
exit:
return ret;
}
int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerprint_t *fp, libosfp_result_t *result)
int libosfp_score_db_score(libosfp_score_db_t *score_db, unsigned int flags, libosfp_fingerprint_t *fp, libosfp_score_t *result_score)
{
int ret = -1, i, j;
void *field_value;
int ret = LIBOSFP_EINVAL, i, j;
unsigned int os_class_score;
unsigned int likely_score;
unsigned int perfect_score;
unsigned int entry_count;
unsigned int importance;
unsigned int field_len;
libosfp_score_t *score;
libosfp_score_db_t *score_db;
libosfp_score_t *matched_score;
libosfp_os_class_id_t likely_os_class;
libosfp_fingerprint_field_t *field;
libosfp_field_score_db_t *field_score_db;
if (libosfp_context == NULL || fp == NULL || result == NULL) {
if (score_db == NULL || fp == NULL || result_score == NULL) {
goto exit;
}
memset(result, 0, sizeof(libosfp_result_t));
memset(result_score, 0, sizeof(libosfp_score_t));
score_db = (libosfp_score_db_t*)libosfp_context->score_db;
perfect_score = score_db->perfect_score;
if (perfect_score == 0) {
goto exit;
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
if (!fp->fields[i].enabled) {
continue;
}
field_score_db = &score_db->field_score_dbs[i];
if (!field_score_db->enabled) {
continue;
}
field_value = fp->fields[i].value;
field_len = fp->fields[i].value_len;
field = &fp->fields[i];
if (!field->enabled) {
continue;
}
score = libosfp_score_db_filed_match(field_score_db, field_value, field_len);
if (score == NULL) {
matched_score = libosfp_score_db_filed_match(field_score_db, field->value, field->value_len);
if (matched_score == NULL) {
continue;
}
importance = libosfp_fingerprint_get_field_importance(i);
for (j = 0; j < LIBOSFP_OS_CLASS_MAX; j++) {
result->score.os_class_score[j] += score->os_class_score[j] * importance;
if (0 == flags || flags & LIBOSFP_BIT_U32(j)) {
result_score->os_class_score[j] += matched_score->os_class_score[j] * importance / perfect_score;
}
}
if (i == LIBOSFP_FIELD_TCP_OPTIONS) {
@@ -452,66 +451,103 @@ int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerpri
}
}
likely_score = result_score->likely_score;
likely_os_class = result_score->likely_os_class;
perfect_score = score_db->perfect_score;
result->perfect_score = perfect_score;
for (j = 0; j < LIBOSFP_OS_CLASS_MAX; j++) {
entry_count = score_db->os_class_entry_count[j];
os_class_score = result->score.os_class_score[j];
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
entry_count = score_db->os_class_entry_count[i];
os_class_score = result_score->os_class_score[i];
if (entry_count == 0 || perfect_score == 0) {
continue;
}
os_class_score = 100 * os_class_score / entry_count;
os_class_score = (unsigned int)((float)os_class_score / (float)perfect_score);
// calc percentile score
os_class_score = (LIBOSFP_PERCENTILE * os_class_score) / entry_count;
if (result->likely_score < os_class_score) {
result->likely_score = os_class_score;
result->likely_os_class = j;
// calc likely os class and score
if (likely_score < os_class_score) {
likely_score = os_class_score;
likely_os_class = i;
}
result->score.os_class_score[j] = os_class_score;
result_score->os_class_score[i] = os_class_score;
}
return 0;
result_score->likely_score = likely_score;
result_score->likely_os_class = likely_os_class;
return LIBOSFP_NOERR;
exit:
return ret;
}
void libosfp_score_db_debug_print(libosfp_score_db_t *score_db)
{
int i;
printf("score_db:\n");
printf("entry_count: %u\n", score_db->entry_count);
printf("perfect_score: %u\n", score_db->perfect_score);
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
const char *name = libosfp_os_class_id_to_name(i);
printf("os class %p ", name);
printf("entry_count: %u\n", score_db->os_class_entry_count[i]);
printf("os class %s entry_count: %u\n", libosfp_os_class_id_to_name(i), score_db->os_class_entry_count[i]);
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
printf("field %s enabled: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].enabled);
printf("field %s type: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].type);
printf("field %s entry_count: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].entry_count);
printf("field %s enabled: %p\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].data);
}
}
libosfp_score_db_t *libosfp_score_db_create(void)
{
int ret = -1, i;
int i;
libosfp_score_db_t *score_db;
libosfp_field_score_db_t *db;
score_db = calloc(1, sizeof(libosfp_score_db_t));
if (score_db == NULL) {
goto exit;
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
db = &score_db->field_score_dbs[i];
db->enabled = libosfp_fingerprint_get_field_enabled(i);
db->type = libosfp_fingerprint_get_field_type(i);
switch (score_db->field_score_dbs[i].type) {
db->enabled = libosfp_fingerprint_get_field_enabled(i);
if (!db->enabled) {
libosfp_log_warning("field disabled: %s", "");
continue;
}
db->type = libosfp_fingerprint_get_field_type(i);
switch (db->type) {
case LIBOSFP_FIELD_TYPE_UINT:
score_db->field_score_dbs[i].create = libosfp_score_db_array_create;
score_db->field_score_dbs[i].destroy = libosfp_score_db_array_destroy;
score_db->field_score_dbs[i].add = libosfp_score_db_array_add;
score_db->field_score_dbs[i].match = libosfp_score_db_array_match;
db->create = libosfp_score_db_array_create;
db->destroy = libosfp_score_db_array_destroy;
db->add = libosfp_score_db_array_add;
db->match = libosfp_score_db_array_match;
break;
case LIBOSFP_FIELD_TYPE_STRING:
score_db->field_score_dbs[i].create = libosfp_score_db_hash_create;
score_db->field_score_dbs[i].destroy = libosfp_score_db_hash_destroy;
score_db->field_score_dbs[i].add = libosfp_score_db_hash_add;
score_db->field_score_dbs[i].match = libosfp_score_db_hash_match;
db->create = libosfp_score_db_hash_create;
db->destroy = libosfp_score_db_hash_destroy;
db->add = libosfp_score_db_hash_add;
db->match = libosfp_score_db_hash_match;
break;
default:
libosfp_log_debug("unsupported type: %u", db->type);
goto exit;
}
db->data = score_db->field_score_dbs[i].create();
db->data = db->create();
if (db->data == NULL) {
continue;
libosfp_log_debug("create failed. field: %s", libosfp_fingerprint_get_field_name(i));
goto exit;
}
}

View File

@@ -1,7 +1,7 @@
#ifndef __LIBOSFP_SCORE_DB_H__
#define __LIBOSFP_SCORE_DB_H__
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_fingerprint.h"
typedef struct libosfp_field_score_db {
@@ -25,10 +25,10 @@ typedef struct libosfp_score_db {
} libosfp_score_db_t;
int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file);
int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerprint_t *fp, libosfp_result_t *result);
int libosfp_score_db_score(libosfp_score_db_t *score_db, unsigned int flags, libosfp_fingerprint_t *fp, libosfp_score_t *result);
void libosfp_score_db_debug_print(libosfp_score_db_t *score_db);
libosfp_score_db_t *libosfp_score_db_create(void);
void libosfp_score_db_destroy(libosfp_score_db_t *score_db);
#endif