use std::time::Instant;
use crate::ffi::api::common::Limits;
use crate::ffi::{borrow_text, Buffer};
use crate::helpers::hsts::HstsStore;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct HstsPolicy {
pub max_age: i64,
pub include_subdomains: bool,
pub preload: bool,
}
impl HstsPolicy {
pub fn parse(&self) -> crate::helpers::hsts::HstsPolicy {
crate::helpers::hsts::HstsPolicy {
max_age: self.max_age,
include_subdomains: self.include_subdomains,
preload: self.preload,
}
}
pub fn build(policy: &crate::helpers::hsts::HstsPolicy) -> Self {
Self {
max_age: policy.max_age,
include_subdomains: policy.include_subdomains,
preload: policy.preload,
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_policy_parse(value: *const u8, value_len: usize, out: *mut HstsPolicy) -> bool {
if out.is_null() {
return false;
}
let Some(value) = (unsafe { borrow_text(value, value_len) }) else {
return false;
};
match crate::helpers::hsts::HstsPolicy::parse(value) {
Some(policy) => {
unsafe { *out = HstsPolicy::build(&policy) };
true
}
None => false,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_policy_build(policy: *const HstsPolicy) -> Buffer {
match unsafe { policy.as_ref() } {
Some(policy) => Buffer::new(policy.parse().build().into_bytes()),
None => Buffer::EMPTY,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_store_new(limits: *const Limits) -> *mut HstsStore {
Box::into_raw(Box::new(HstsStore::new().with_limits(unsafe { Limits::or_default(limits) })))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_store_free(store: *mut HstsStore) {
if !store.is_null() {
drop(unsafe { Box::from_raw(store) });
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_store_learn(store: *const HstsStore, host: *const u8, host_len: usize, header: *const u8, header_len: usize, secure: bool) -> bool {
let (Some(store), Some(host), Some(header)) = (unsafe { store.as_ref() }, unsafe { borrow_text(host, host_len) }, unsafe { borrow_text(header, header_len) })
else {
return false;
};
store.learn(host, header, secure, Instant::now());
true
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn soyokaze_hsts_store_secure(store: *const HstsStore, host: *const u8, host_len: usize) -> bool {
let (Some(store), Some(host)) = (unsafe { store.as_ref() }, unsafe { borrow_text(host, host_len) }) else {
return false;
};
store.secure(host, Instant::now())
}