Skip to content

Commit daddf95

Browse files
committed
Added codesign checker for macos
1 parent 042d116 commit daddf95

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ license = "MIT"
1111
repository = "https://github.com/Choochmeque/tauri-plugin-iap"
1212

1313
[features]
14-
unstable = ["dep:swift-bridge", "dep:serde_json"]
14+
default = ["unstable"]
15+
unstable = ["dep:swift-bridge", "dep:serde_json", "dep:objc2", "dep:objc2-core-foundation", "dep:objc2-security"]
1516

1617
[dependencies]
1718
tauri = { version = "2.7.0" }
@@ -21,6 +22,9 @@ thiserror = "2"
2122
[target.'cfg(target_os = "macos")'.dependencies]
2223
swift-bridge = { version = "0.1", features = ["async"], optional = true}
2324
serde_json = { version = "1.0", optional = true }
25+
objc2 = { version = "0.6", optional = true }
26+
objc2-core-foundation = { version = "0.3", optional = true }
27+
objc2-security = { version = "0.3", optional = true }
2428

2529
[build-dependencies]
2630
tauri-plugin = { version = "2.3.0", features = ["build"] }

src/macos.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,46 @@ use tauri::{plugin::PluginApi, AppHandle, Runtime};
33

44
use crate::models::*;
55

6+
mod codesign {
7+
use objc2_security::{kSecCSCheckAllArchitectures, kSecCSCheckNestedCode, kSecCSStrictValidate, SecCSFlags, SecCode};
8+
use std::ptr::NonNull;
9+
10+
/// Returns `Ok(())` if the running binary is code-signed and valid, otherwise returns an Error.
11+
pub fn is_signature_valid() -> crate::Result<()> {
12+
unsafe {
13+
// 1) Get a handle to "self"
14+
let mut self_code: *mut SecCode = std::ptr::null_mut();
15+
let self_code_ptr = NonNull::<*mut SecCode>::new_unchecked(&mut self_code);
16+
let status = SecCode::copy_self(SecCSFlags::empty(), self_code_ptr);
17+
if status != 0 {
18+
return Err(std::io::Error::new(
19+
std::io::ErrorKind::Other,
20+
format!("Failed to get code reference: OSStatus {}", status),
21+
)
22+
.into());
23+
}
24+
25+
// 2) Validate the dynamic code - this checks if the signature is valid
26+
let validity_flags = SecCSFlags(kSecCSCheckAllArchitectures | kSecCSCheckNestedCode | kSecCSStrictValidate);
27+
let self_code_ref = self_code_ptr.as_ref().as_ref().unwrap();
28+
let status = SecCode::check_validity(
29+
self_code_ref,
30+
validity_flags,
31+
None,
32+
);
33+
if status != 0 {
34+
return Err(std::io::Error::new(
35+
std::io::ErrorKind::Other,
36+
format!("Code signature validation failed: OSStatus {}", status),
37+
)
38+
.into());
39+
}
40+
41+
Ok(())
42+
}
43+
}
44+
}
45+
646
#[swift_bridge::bridge]
747
mod ffi {
848
pub enum FFIResult {
@@ -47,6 +87,8 @@ impl<R: Runtime> Iap<R> {
4787
}
4888

4989
pub fn initialize(&self) -> crate::Result<InitializeResponse> {
90+
codesign::is_signature_valid()?;
91+
5092
Self::to_result(ffi::initialize())
5193
}
5294

@@ -55,6 +97,8 @@ impl<R: Runtime> Iap<R> {
5597
product_ids: Vec<String>,
5698
product_type: String,
5799
) -> crate::Result<GetProductsResponse> {
100+
codesign::is_signature_valid()?;
101+
58102
Self::to_result(ffi::getProducts(product_ids, product_type))
59103
}
60104

@@ -64,20 +108,26 @@ impl<R: Runtime> Iap<R> {
64108
product_type: String,
65109
offer_token: Option<String>,
66110
) -> crate::Result<Purchase> {
111+
codesign::is_signature_valid()?;
112+
67113
Self::to_result(ffi::purchase(product_id, product_type, offer_token))
68114
}
69115

70116
pub fn restore_purchases(
71117
&self,
72118
product_type: String,
73119
) -> crate::Result<RestorePurchasesResponse> {
120+
codesign::is_signature_valid()?;
121+
74122
Self::to_result(ffi::restorePurchases(product_type))
75123
}
76124

77125
pub fn acknowledge_purchase(
78126
&self,
79127
purchase_token: String,
80128
) -> crate::Result<AcknowledgePurchaseResponse> {
129+
codesign::is_signature_valid()?;
130+
81131
Self::to_result(ffi::acknowledgePurchase(purchase_token))
82132
}
83133

@@ -86,6 +136,8 @@ impl<R: Runtime> Iap<R> {
86136
product_id: String,
87137
product_type: String,
88138
) -> crate::Result<ProductStatus> {
139+
codesign::is_signature_valid()?;
140+
89141
Self::to_result(ffi::getProductStatus(product_id, product_type))
90142
}
91143
}

0 commit comments

Comments
 (0)