From 031456e41d4b1bc5a185934fb7a0a506618d3a8d Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Thu, 16 May 2024 16:44:24 -0300 Subject: [PATCH] Add more core API's to rust --- rust/src/enterprise.rs | 196 +++++++++++++++++++++++++++++++++++++++++ rust/src/headless.rs | 4 + rust/src/lib.rs | 70 +++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 rust/src/enterprise.rs diff --git a/rust/src/enterprise.rs b/rust/src/enterprise.rs new file mode 100644 index 000000000..8065a7a32 --- /dev/null +++ b/rust/src/enterprise.rs @@ -0,0 +1,196 @@ +use std::marker::PhantomData; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use crate::rc::Array; +use crate::string::{BnStrCompatible, BnString}; + +pub fn server_username() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUsername()) } +} + +pub fn server_url() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUrl()) } +} + +pub fn set_server_url(url: S) -> Result<(), ()> { + let url = url.into_bytes_with_nul(); + let result = unsafe { + binaryninjacore_sys::BNSetEnterpriseServerUrl(url.as_ref().as_ptr() as *const i8) + }; + if result { + Ok(()) + } else { + Err(()) + } +} + +pub fn server_name() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerName()) } +} + +pub fn server_id() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerId()) } +} + +pub fn server_version() -> u64 { + unsafe { binaryninjacore_sys::BNGetEnterpriseServerVersion() } +} + +pub fn server_build_id() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerBuildId()) } +} + +pub fn server_token() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerToken()) } +} + +pub fn license_duration() -> Duration { + Duration::from_secs(unsafe { binaryninjacore_sys::BNGetEnterpriseServerLicenseDuration() }) +} + +pub fn license_expiration_time() -> SystemTime { + let m = Duration::from_secs(unsafe { + binaryninjacore_sys::BNGetEnterpriseServerLicenseExpirationTime() + }); + UNIX_EPOCH + m +} + +pub fn server_reservation_time_limit() -> Duration { + Duration::from_secs(unsafe { binaryninjacore_sys::BNGetEnterpriseServerReservationTimeLimit() }) +} + +pub fn is_server_floating_license() -> bool { + unsafe { binaryninjacore_sys::BNIsEnterpriseServerFloatingLicense() } +} + +pub fn is_server_license_still_activated() -> bool { + unsafe { binaryninjacore_sys::BNIsEnterpriseServerLicenseStillActivated() } +} + +pub fn authenticate_server_with_credentials(username: U, password: P, remember: bool) -> bool +where + U: BnStrCompatible, + P: BnStrCompatible, +{ + let username = username.into_bytes_with_nul(); + let password = password.into_bytes_with_nul(); + unsafe { + binaryninjacore_sys::BNAuthenticateEnterpriseServerWithCredentials( + username.as_ref().as_ptr() as *const i8, + password.as_ref().as_ptr() as *const i8, + remember, + ) + } +} + +pub fn authenticate_server_with_method(method: S, remember: bool) -> bool { + let method = method.into_bytes_with_nul(); + unsafe { + binaryninjacore_sys::BNAuthenticateEnterpriseServerWithMethod( + method.as_ref().as_ptr() as *const i8, + remember, + ) + } +} + +pub fn connect_server() -> bool { + unsafe { binaryninjacore_sys::BNConnectEnterpriseServer() } +} + +pub fn deauthenticate_server() -> bool { + unsafe { binaryninjacore_sys::BNDeauthenticateEnterpriseServer() } +} + +pub fn cancel_server_authentication() { + unsafe { binaryninjacore_sys::BNCancelEnterpriseServerAuthentication() } +} + +pub fn update_server_license(timeout: Duration) -> bool { + unsafe { binaryninjacore_sys::BNUpdateEnterpriseServerLicense(timeout.as_secs()) } +} + +pub fn release_server_license() -> bool { + unsafe { binaryninjacore_sys::BNReleaseEnterpriseServerLicense() } +} + +pub fn is_server_connected() -> bool { + unsafe { binaryninjacore_sys::BNIsEnterpriseServerConnected() } +} + +pub fn is_server_authenticated() -> bool { + unsafe { binaryninjacore_sys::BNIsEnterpriseServerAuthenticated() } +} + +pub fn is_server_initialized() -> bool { + unsafe { binaryninjacore_sys::BNIsEnterpriseServerInitialized() } +} + +pub fn server_last_error() -> BnString { + unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerLastError()) } +} + +pub fn server_authentication_methods() -> (Array, Array) { + let mut methods = core::ptr::null_mut(); + let mut names = core::ptr::null_mut(); + let count = unsafe { + binaryninjacore_sys::BNGetEnterpriseServerAuthenticationMethods(&mut methods, &mut names) + }; + unsafe { (Array::new(methods, count, ()), Array::new(names, count, ())) } +} + +// NOTE don't implement Clone, Copy, so each callback can only be +// register/unregistered only once +#[repr(transparent)] +#[derive(Debug)] +pub struct EnterpriseServerCallback<'a> { + handle: binaryninjacore_sys::BNEnterpriseServerCallbacks, + lifetime: PhantomData<&'a ()>, +} + +pub fn register_license_changed_callback<'a, F: FnMut(bool) + 'a>( + callback: F, +) -> EnterpriseServerCallback<'a> { + unsafe extern "C" fn cb_license_status_changed( + ctxt: *mut ::std::os::raw::c_void, + still_valid: bool, + ) { + let ctxt: &mut F = &mut *(ctxt as *mut F); + ctxt(still_valid) + } + let mut handle = binaryninjacore_sys::BNEnterpriseServerCallbacks { + context: Box::leak(Box::new(callback)) as *mut F as *mut core::ffi::c_void, + licenseStatusChanged: Some(cb_license_status_changed::), + }; + unsafe { binaryninjacore_sys::BNRegisterEnterpriseServerNotification(&mut handle) } + EnterpriseServerCallback { + handle, + lifetime: PhantomData, + } +} + +pub fn unregister_license_changed_callback(mut callback_handle: EnterpriseServerCallback) { + unsafe { + binaryninjacore_sys::BNUnregisterEnterpriseServerNotification(&mut callback_handle.handle) + } +} + +impl<'a> EnterpriseServerCallback<'a> { + /// register the license changed callback + pub fn register(callback: F) -> Self { + register_license_changed_callback(callback) + } + + /// deregister the license changed callback, equivalent to drop the struct + pub fn deregister(self) { + // Nothing, just drop self + } +} + +impl Drop for EnterpriseServerCallback<'_> { + fn drop(&mut self) { + unregister_license_changed_callback(EnterpriseServerCallback { + handle: self.handle, + lifetime: PhantomData, + }) + } +} diff --git a/rust/src/headless.rs b/rust/src/headless.rs index d4d8892ab..fdde2608f 100644 --- a/rust/src/headless.rs +++ b/rust/src/headless.rs @@ -99,6 +99,10 @@ pub fn shutdown() { unsafe { binaryninjacore_sys::BNShutdown() }; } +pub fn is_shutdown_requested() { + unsafe { binaryninjacore_sys::BNIsShutdownRequested() }; +} + /// Prelued-postlued helper function (calls [`init`] and [`shutdown`] for you) /// ```no_run /// # use binaryninja::binaryview::BinaryViewExt; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index c086478d9..baac888b4 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -138,6 +138,7 @@ pub mod databuffer; pub mod debuginfo; pub mod demangle; pub mod disassembly; +pub mod enterprise; pub mod component; pub mod downloadprovider; pub mod externallibrary; @@ -434,6 +435,75 @@ pub fn version() -> string::BnString { unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetVersionString()) } } +pub fn build_id() -> u32 { + unsafe { binaryninjacore_sys::BNGetBuildId() } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct VersionInfo { + pub major: u32, + pub minor: u32, + pub build: u32, + pub channel: string::BnString, +} + +pub fn version_info() -> VersionInfo { + let info_raw = unsafe { binaryninjacore_sys::BNGetVersionInfo() }; + VersionInfo { + major: info_raw.major, + minor: info_raw.minor, + build: info_raw.build, + channel: unsafe { string::BnString::from_raw(info_raw.channel) }, + } +} + +pub fn serial_number() -> string::BnString { + unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetSerialNumber()) } +} + +pub fn is_license_validated() -> bool { + unsafe { binaryninjacore_sys::BNIsLicenseValidated() } +} + +pub fn licensed_user_email() -> string::BnString { + unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetLicensedUserEmail()) } +} + +pub fn license_count() -> i32 { + unsafe { binaryninjacore_sys::BNGetLicenseCount() } +} + +pub fn set_license(license: S) { + let license = license.into_bytes_with_nul(); + let license_slice = license.as_ref(); + unsafe { binaryninjacore_sys::BNSetLicense(license_slice.as_ptr() as *const i8) } +} + +pub fn product() -> string::BnString { + unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetProduct()) } +} + +pub fn product_type() -> string::BnString { + unsafe { string::BnString::from_raw(binaryninjacore_sys::BNGetProductType()) } +} + +pub fn license_expiration_time() -> std::time::SystemTime { + let m = std::time::Duration::from_secs(unsafe { + binaryninjacore_sys::BNGetLicenseExpirationTime() + }); + std::time::UNIX_EPOCH + m +} + +pub fn is_ui_enabled() -> bool { + unsafe { binaryninjacore_sys::BNIsUIEnabled() } +} + +pub fn is_database(filename: S) -> bool { + let filename = filename.into_bytes_with_nul(); + let filename_slice = filename.as_ref(); + unsafe { binaryninjacore_sys::BNIsDatabase(filename_slice.as_ptr() as *const i8) } +} + pub fn plugin_abi_version() -> u32 { binaryninjacore_sys::BN_CURRENT_CORE_ABI_VERSION }