summaryrefslogtreecommitdiff
path: root/rust/src/enterprise.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/enterprise.rs')
-rw-r--r--rust/src/enterprise.rs84
1 files changed, 54 insertions, 30 deletions
diff --git a/rust/src/enterprise.rs b/rust/src/enterprise.rs
index 5b8877f3..34fa8a03 100644
--- a/rust/src/enterprise.rs
+++ b/rust/src/enterprise.rs
@@ -1,59 +1,68 @@
-use std::marker::PhantomData;
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
-
use crate::rc::Array;
use crate::string::{BnStrCompatible, BnString};
+use std::marker::PhantomData;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+use thiserror::Error;
-
-#[derive(Debug)]
-pub struct EnterpriseCheckoutError(pub String);
-
-impl std::fmt::Display for EnterpriseCheckoutError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.0)
- }
+#[derive(Error, Debug)]
+pub enum EnterpriseCheckoutError {
+ #[error("enterprise server returned error: {0}")]
+ ServerError(String),
+ #[error("no username set for credential authentication")]
+ NoUsername,
+ #[error("no password set for credential authentication")]
+ NoPassword,
+ #[error("failed to authenticate with username and password")]
+ NotAuthenticated,
+ #[error("failed to refresh expired license")]
+ RefreshExpiredLicenseFailed,
}
-impl std::error::Error for EnterpriseCheckoutError {}
-
+/// Initialize the enterprise server connection to check out a floating license.
pub fn checkout_license(duration: Duration) -> Result<(), EnterpriseCheckoutError> {
if crate::is_ui_enabled() {
+ // We only need to check out a license if running headlessly.
return Ok(());
}
+ #[allow(clippy::collapsible_if)]
if !is_server_initialized() {
+ // We need to first initialize the server.
if !initialize_server() && is_server_floating_license() {
- return Err(EnterpriseCheckoutError(server_last_error().to_string()));
+ let last_error = server_last_error().to_string();
+ return Err(EnterpriseCheckoutError::ServerError(last_error));
}
}
if is_server_floating_license() {
if !is_server_connected() && !connect_server() {
- return Err(EnterpriseCheckoutError(server_last_error().to_string()));
+ let last_error = server_last_error().to_string();
+ return Err(EnterpriseCheckoutError::ServerError(last_error));
}
+ #[allow(clippy::collapsible_if)]
if !is_server_authenticated() {
+ // We have yet to authenticate with the server, we should try all available authentication methods.
if !authenticate_server_with_method("Keychain", false) {
- let Some(username) = std::env::var("BN_ENTERPRISE_USERNAME").ok() else {
- return Err(EnterpriseCheckoutError("BN_ENTERPRISE_USERNAME not set when attempting to authenticate with credentials".to_string()));
- };
- let Some(password) = std::env::var("BN_ENTERPRISE_PASSWORD").ok() else {
- return Err(EnterpriseCheckoutError("BN_ENTERPRISE_PASSWORD not set when attempting to authenticate with credentials".to_string()));
- };
+ // We could not authenticate with the system keychain, we should try with credentials.
+ let username = std::env::var("BN_ENTERPRISE_USERNAME")
+ .map_err(|_| EnterpriseCheckoutError::NoUsername)?;
+ let password = std::env::var("BN_ENTERPRISE_PASSWORD")
+ .map_err(|_| EnterpriseCheckoutError::NoPassword)?;
if !authenticate_server_with_credentials(username, password, true) {
- let failed_message = "Could not checkout a license: Not authenticated. Try one of the following: \n \
- - Log in and check out a license for an extended time\n \
- - Set BN_ENTERPRISE_USERNAME and BN_ENTERPRISE_PASSWORD environment variables\n \
- - Use binaryninja::enterprise::{authenticate_server_with_method OR authenticate_server_with_credentials} in your code";
- return Err(EnterpriseCheckoutError(failed_message.to_string()));
+ return Err(EnterpriseCheckoutError::NotAuthenticated);
}
}
}
}
-
- if !is_server_license_still_activated() || (!is_server_floating_license() && crate::license_expiration_time() < SystemTime::now()) {
+
+ #[allow(clippy::collapsible_if)]
+ if !is_server_license_still_activated()
+ || (!is_server_floating_license() && crate::license_expiration_time() < SystemTime::now())
+ {
+ // If the license is expired we should refresh the license.
if !update_server_license(duration) {
- return Err(EnterpriseCheckoutError("Failed to refresh expired license".to_string()));
+ return Err(EnterpriseCheckoutError::RefreshExpiredLicenseFailed);
}
}
@@ -62,14 +71,27 @@ pub fn checkout_license(duration: Duration) -> Result<(), EnterpriseCheckoutErro
pub fn release_license() {
if !crate::is_ui_enabled() {
+ // This might look dumb, why would we want to connect to the server, would that not just mean
+ // we don't need to release the license? Well no, you could have run a script, acquired a license for 10 hours
+ // then you WOULD want to call release license, and your expectation is that acquired license
+ // will now be released. To release that you must have an active connection which is what this does.
+ if !is_server_initialized() {
+ initialize_server();
+ }
+ if !is_server_connected() {
+ connect_server();
+ }
+ // We should only release the license if we are running headlessly.
release_server_license();
}
}
+// TODO: If "" string return None
pub fn server_username() -> BnString {
unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUsername()) }
}
+// TODO: If "" string return None
pub fn server_url() -> BnString {
unsafe { BnString::from_raw(binaryninjacore_sys::BNGetEnterpriseServerUrl()) }
}
@@ -77,7 +99,9 @@ pub fn server_url() -> BnString {
pub fn set_server_url<S: BnStrCompatible>(url: S) -> Result<(), ()> {
let url = url.into_bytes_with_nul();
let result = unsafe {
- binaryninjacore_sys::BNSetEnterpriseServerUrl(url.as_ref().as_ptr() as *const std::os::raw::c_char)
+ binaryninjacore_sys::BNSetEnterpriseServerUrl(
+ url.as_ref().as_ptr() as *const std::os::raw::c_char
+ )
};
if result {
Ok(())