use chrono::serde::ts_seconds_option;
use chrono::{DateTime, Utc};
use duration_string::DurationString;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
pub const MDB_VERSION: &str = env!("CARGO_PKG_VERSION");
pub const USER_LOGIN_URL: &str = "/v1/users/getkey";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GetAPIKeyRequest {
pub user: String,
pub password: String,
}
pub const USER_LOGOUT_URL: &str = "/v1/users/clearkey";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GetAPIKeyResponse {
pub key: Option<String>,
pub message: Option<String>,
}
pub const USER_INFO_URL: &str = "/v1/users/info";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GetUserInfoResponse {
pub id: i32,
pub username: String,
pub groups: Vec<String>,
pub sources: Vec<String>,
pub is_admin: bool,
}
pub const SERVER_INFO: &str = "/v1/server/info";
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct ServerInfo {
pub os_name: String,
pub os_version: String,
pub memory_used: String,
pub mdb_version: String,
pub db_version: String,
pub db_size: String,
pub num_samples: u64,
pub num_users: u32,
pub uptime: DurationString,
}
pub const SUPPORTED_FILE_TYPES: &str = "/v1/server/types";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SupportedFileType {
pub name: String,
pub magic: Vec<String>,
pub is_executable: bool,
pub description: Option<String>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SupportedFileTypes {
pub types: Vec<SupportedFileType>,
pub message: Option<String>,
}
pub const GET_SOURCES: &str = "/v1/sources/list";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EmptyAuthenticatingPost {
pub key: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SourceInfo {
pub id: u64,
pub name: String,
pub description: Option<String>,
pub url: Option<String>,
#[serde(with = "ts_seconds_option")]
pub first_acquisition: Option<DateTime<Utc>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Sources {
pub sources: Vec<SourceInfo>,
pub message: Option<String>,
}
pub const UPLOAD_SAMPLE: &str = "/v1/samples/upload";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NewSample {
pub file_name: String,
pub key: String,
pub source_id: u32,
pub file_contents_b64: String,
pub sha256: String,
}
pub const DOWNLOAD_SAMPLE: &str = "/v1/samples/download";
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum HashType {
Md5(String),
SHA1(String),
SHA256(String),
SHA384(String),
SHA512(String),
}
impl Display for HashType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
HashType::Md5(h) => write!(f, "MD5: {h}"),
HashType::SHA1(h) => write!(f, "SHA-1: {h}"),
HashType::SHA256(h) => write!(f, "SHA-256: {h}"),
HashType::SHA384(h) => write!(f, "SHA-384: {h}"),
HashType::SHA512(h) => write!(f, "SHA-512: {h}"),
}
}
}
impl HashType {
pub fn name(&self) -> &'static str {
match self {
HashType::Md5(_) => "md5",
HashType::SHA1(_) => "sha1",
HashType::SHA256(_) => "sha256",
HashType::SHA384(_) => "sha384",
HashType::SHA512(_) => "sha512",
}
}
pub fn the_hash(&self) -> &String {
match self {
HashType::Md5(h)
| HashType::SHA1(h)
| HashType::SHA256(h)
| HashType::SHA384(h)
| HashType::SHA512(h) => h,
}
}
}
impl TryFrom<String> for HashType {
type Error = &'static str;
fn try_from(value: String) -> Result<Self, Self::Error> {
Ok(match value.len() {
32 => HashType::Md5(value),
40 => HashType::SHA1(value),
64 => HashType::SHA256(value),
96 => HashType::SHA384(value),
128 => HashType::SHA512(value),
_ => return Err("unknown hash size"),
})
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DownloadSampleRequest {
pub key: String,
pub hash: HashType,
}
pub const SIMILAR_SAMPLES: &str = "/v1/samples/similar";
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[non_exhaustive]
pub enum SimilarityHashType {
SSDeep,
SDHash,
LZJD,
TLSH,
PEHash,
ImportHash,
FuzzyImportHash,
}
impl SimilarityHashType {
pub fn get_table_field_simfunc(&self) -> (&'static str, Option<&'static str>) {
match self {
SimilarityHashType::SSDeep => ("file.ssdeep", Some("fuzzy_hash_compare")),
SimilarityHashType::SDHash => ("file.sdhash", Some("sdhash_compare")),
SimilarityHashType::LZJD => ("file.lzjd", Some("lzjd_compare")),
SimilarityHashType::TLSH => ("file.tlsh", Some("tlsh_compare")),
SimilarityHashType::PEHash => ("executable.pehash", None),
SimilarityHashType::ImportHash => ("executable.importhash", None),
SimilarityHashType::FuzzyImportHash => {
("executable.importhashfuzzy", Some("fuzzy_hash_compare"))
}
}
}
}
impl Display for SimilarityHashType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SimilarityHashType::SSDeep => write!(f, "SSDeep"),
SimilarityHashType::SDHash => write!(f, "SDHash"),
SimilarityHashType::LZJD => write!(f, "LZJD"),
SimilarityHashType::TLSH => write!(f, "TLSH"),
SimilarityHashType::PEHash => write!(f, "PeHash"),
SimilarityHashType::ImportHash => write!(f, "Import Hash (IMPHASH)"),
SimilarityHashType::FuzzyImportHash => write!(f, "Fuzzy Import hash"),
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SimilarSamplesRequest {
pub key: String,
pub hash: Vec<(SimilarityHashType, String)>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SimilarSample {
pub sha256: String,
pub algorithms: Vec<(SimilarityHashType, f32)>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct SimilarSamplesResponse {
pub results: Vec<SimilarSample>,
pub message: Option<String>,
}