binaryninja/
secrets_provider.rs1use binaryninjacore_sys::*;
2use std::ffi::{c_char, c_void, CStr};
3use std::fmt::Debug;
4use std::ptr::NonNull;
5
6use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner};
7use crate::string::{BnString, IntoCStr};
8
9pub trait SecretsProvider {
10 fn has_data(&mut self, key: &str) -> bool;
11 fn get_data(&mut self, key: &str) -> Option<String>;
12 fn store_data(&mut self, key: &str, data: &str) -> bool;
13 fn delete_data(&mut self, key: &str) -> bool;
14}
15
16#[repr(transparent)]
18pub struct CoreSecretsProvider {
19 handle: NonNull<BNSecretsProvider>,
20}
21
22impl CoreSecretsProvider {
23 pub(crate) unsafe fn from_raw(handle: NonNull<BNSecretsProvider>) -> Self {
24 Self { handle }
25 }
26
27 pub fn new<C: SecretsProvider>(name: &str, callback: C) -> Self {
29 let name = name.to_cstr();
31 let callback = Box::leak(Box::new(callback));
32 let mut callbacks = BNSecretsProviderCallbacks {
33 context: callback as *mut C as *mut c_void,
34 hasData: Some(cb_has_data::<C>),
35 getData: Some(cb_get_data::<C>),
36 storeData: Some(cb_store_data::<C>),
37 deleteData: Some(cb_delete_data::<C>),
38 };
39 let result = unsafe { BNRegisterSecretsProvider(name.as_ptr(), &mut callbacks) };
40 unsafe { Self::from_raw(NonNull::new(result).unwrap()) }
41 }
42
43 pub fn all() -> Array<CoreSecretsProvider> {
45 let mut count = 0;
46 let result = unsafe { BNGetSecretsProviderList(&mut count) };
47 assert!(!result.is_null());
48 unsafe { Array::new(result, count, ()) }
49 }
50
51 pub fn by_name(name: &str) -> Option<CoreSecretsProvider> {
53 let name = name.to_cstr();
54 let result = unsafe { BNGetSecretsProviderByName(name.as_ptr()) };
55 NonNull::new(result).map(|h| unsafe { Self::from_raw(h) })
56 }
57
58 pub fn name(&self) -> String {
59 let result = unsafe { BNGetSecretsProviderName(self.handle.as_ptr()) };
60 assert!(!result.is_null());
61 unsafe { BnString::into_string(result) }
62 }
63
64 pub fn has_data(&self, key: &str) -> bool {
66 let key = key.to_cstr();
67 unsafe { BNSecretsProviderHasData(self.handle.as_ptr(), key.as_ptr()) }
68 }
69
70 pub fn get_data(&self, key: &str) -> String {
72 let key = key.to_cstr();
73 let result = unsafe { BNGetSecretsProviderData(self.handle.as_ptr(), key.as_ptr()) };
74 unsafe { BnString::into_string(result) }
75 }
76
77 pub fn store_data(&self, key: &str, value: &str) -> bool {
79 let key = key.to_cstr();
80 let value = value.to_cstr();
81 unsafe { BNStoreSecretsProviderData(self.handle.as_ptr(), key.as_ptr(), value.as_ptr()) }
82 }
83
84 pub fn delete_data(&self, key: &str) -> bool {
86 let key = key.to_cstr();
87 unsafe { BNDeleteSecretsProviderData(self.handle.as_ptr(), key.as_ptr()) }
88 }
89}
90
91impl Debug for CoreSecretsProvider {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.debug_struct("CoreSecretsProvider")
94 .field("name", &self.name())
95 .finish()
96 }
97}
98
99impl CoreArrayProvider for CoreSecretsProvider {
100 type Raw = *mut BNSecretsProvider;
101 type Context = ();
102 type Wrapped<'a> = Self;
103}
104
105unsafe impl CoreArrayProviderInner for CoreSecretsProvider {
106 unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
107 BNFreeSecretsProviderList(raw)
108 }
109
110 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
111 let raw_ptr = NonNull::new(*raw).unwrap();
112 Self::from_raw(raw_ptr)
113 }
114}
115
116unsafe extern "C" fn cb_has_data<C: SecretsProvider>(
117 ctxt: *mut c_void,
118 key: *const c_char,
119) -> bool {
120 let ctxt: &mut C = &mut *(ctxt as *mut C);
121 ctxt.has_data(&CStr::from_ptr(key).to_string_lossy())
122}
123
124unsafe extern "C" fn cb_get_data<C: SecretsProvider>(
125 ctxt: *mut c_void,
126 key: *const c_char,
127) -> *mut c_char {
128 let ctxt: &mut C = &mut *(ctxt as *mut C);
129 match ctxt.get_data(&CStr::from_ptr(key).to_string_lossy()) {
130 Some(result) => BnString::into_raw(BnString::new(result)),
131 None => std::ptr::null_mut(),
132 }
133}
134
135unsafe extern "C" fn cb_store_data<C: SecretsProvider>(
136 ctxt: *mut c_void,
137 key: *const c_char,
138 data: *const c_char,
139) -> bool {
140 let ctxt: &mut C = &mut *(ctxt as *mut C);
141 let key = CStr::from_ptr(key).to_string_lossy();
142 let data = CStr::from_ptr(data).to_string_lossy();
143 ctxt.store_data(&key, &data)
144}
145
146unsafe extern "C" fn cb_delete_data<C: SecretsProvider>(
147 ctxt: *mut c_void,
148 key: *const c_char,
149) -> bool {
150 let ctxt: &mut C = &mut *(ctxt as *mut C);
151 ctxt.delete_data(&CStr::from_ptr(key).to_string_lossy())
152}