Skip to content

Commit d488a7f

Browse files
committed
Enterprise: Add AuthenticateWithToken api
For when you have a token and want to auth with it directly
1 parent 6c34643 commit d488a7f

5 files changed

Lines changed: 87 additions & 12 deletions

File tree

binaryninjacore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4063,6 +4063,8 @@ extern "C"
40634063
BINARYNINJACOREAPI bool BNIsDatabase(const char* filename);
40644064
BINARYNINJACOREAPI bool BNIsDatabaseFromData(const void* data, size_t len);
40654065

4066+
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithToken(
4067+
const char* token, bool remember);
40664068
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithCredentials(
40674069
const char* username, const char* password, bool remember);
40684070
BINARYNINJACOREAPI bool BNAuthenticateEnterpriseServerWithMethod(const char* method, bool remember);

enterprise.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ bool BinaryNinja::Enterprise::Initialize()
3636
}
3737

3838

39+
bool BinaryNinja::Enterprise::AuthenticateWithToken(const std::string& token, bool remember)
40+
{
41+
return BNAuthenticateEnterpriseServerWithToken(token.c_str(), remember);
42+
}
43+
44+
3945
bool BinaryNinja::Enterprise::AuthenticateWithCredentials(const std::string& username, const std::string& password, bool remember)
4046
{
4147
return BNAuthenticateEnterpriseServerWithCredentials(username.c_str(), password.c_str(), remember);
@@ -281,11 +287,20 @@ BinaryNinja::Enterprise::LicenseCheckout::LicenseCheckout(int64_t duration): m_a
281287
}
282288
}
283289
if (!gotAuth)
290+
{
291+
char* token = getenv("BN_ENTERPRISE_TOKEN");
292+
if (token)
293+
{
294+
gotAuth = AuthenticateWithToken(token, true);
295+
}
296+
}
297+
if (!gotAuth)
284298
{
285299
throw EnterpriseException(
286300
"Could not checkout a license: Not authenticated. Try one of the following: \n"
287301
" - Log in and check out a license for an extended time\n"
288302
" - Set BN_ENTERPRISE_USERNAME and BN_ENTERPRISE_PASSWORD environment variables\n"
303+
" - Set BN_ENTERPRISE_TOKEN environment variable\n"
289304
" - Use BinaryNinja::Enterprise::AuthenticateWithCredentials or AuthenticateWithMethod in your code"
290305
);
291306
}

enterprise.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ namespace BinaryNinja
5252
*/
5353
bool Initialize();
5454

55+
/*!
56+
Authenticate to the server with an access token
57+
\param token Token of auth session
58+
\param remember Remember token in keychain
59+
\return True if successful
60+
*/
61+
bool AuthenticateWithToken(const std::string& token, bool remember);
62+
5563
/*!
5664
Authenticate to the Enterprise server with username and password
5765
\param username Username to authenticate with

python/enterprise.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ def is_connected() -> bool:
5454
return core.BNIsEnterpriseServerConnected()
5555

5656

57+
def authenticate_with_token(token: str, remember: bool = True):
58+
"""
59+
Authenticate to the server with an access token
60+
61+
:param str token: Token of auth session.
62+
:param bool remember: Remember token in keychain
63+
"""
64+
if not is_connected():
65+
connect()
66+
if not core.BNAuthenticateEnterpriseServerWithToken(token, remember):
67+
raise RuntimeError(last_error())
68+
69+
5770
def authenticate_with_credentials(username: str, password: str, remember: bool = True):
5871
"""
5972
Authenticate to the Enterprise Server with username/password credentials.
@@ -392,11 +405,20 @@ def acquire(self):
392405
except RuntimeError:
393406
pass
394407

408+
if not got_auth and \
409+
os.environ.get('BN_ENTERPRISE_TOKEN') is not None:
410+
try:
411+
authenticate_with_token(os.environ['BN_ENTERPRISE_TOKEN'])
412+
got_auth = True
413+
except RuntimeError:
414+
pass
415+
395416
if not got_auth:
396417
raise RuntimeError(
397418
"Could not checkout a license: Not authenticated. Try one of the following: \n"
398419
" - Log in and check out a license for an extended time\n"
399420
" - Set BN_ENTERPRISE_USERNAME and BN_ENTERPRISE_PASSWORD environment variables\n"
421+
" - Set BN_ENTERPRISE_TOKEN environment variable\n"
400422
" - Use binaryninja.enterprise.authenticate_with_credentials or authenticate_with_method in your code"
401423
)
402424

rust/src/enterprise.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ use thiserror::Error;
99
pub enum EnterpriseCheckoutError {
1010
#[error("enterprise server returned error: {0}")]
1111
ServerError(String),
12-
#[error("no username set for credential authentication")]
13-
NoUsername,
14-
#[error("no password set for credential authentication")]
15-
NoPassword,
12+
#[error("no credentials set for authentication")]
13+
NoCredentials,
1614
#[error("failed to authenticate with username and password")]
1715
NotAuthenticated,
1816
#[error("failed to refresh expired license: {0}")]
@@ -59,16 +57,36 @@ pub fn checkout_license(
5957

6058
#[allow(clippy::collapsible_if)]
6159
if !is_server_authenticated() {
62-
// We have yet to authenticate with the server, we should try all available authentication methods.
63-
if !authenticate_server_with_method("Keychain", false) {
60+
'auth: {
61+
// We have yet to authenticate with the server, we should try all available authentication methods.
62+
if authenticate_server_with_method("Keychain", false) {
63+
break 'auth;
64+
}
65+
6466
// We could not authenticate with the system keychain, we should try with credentials.
65-
let username = std::env::var("BN_ENTERPRISE_USERNAME")
66-
.map_err(|_| EnterpriseCheckoutError::NoUsername)?;
67-
let password = std::env::var("BN_ENTERPRISE_PASSWORD")
68-
.map_err(|_| EnterpriseCheckoutError::NoPassword)?;
69-
if !authenticate_server_with_credentials(&username, &password, true) {
70-
return Err(EnterpriseCheckoutError::NotAuthenticated);
67+
let username = std::env::var("BN_ENTERPRISE_USERNAME");
68+
let password = std::env::var("BN_ENTERPRISE_PASSWORD");
69+
if let Ok(username) = username {
70+
if let Ok(password) = password {
71+
// Having creds that don't work is a hard error
72+
if !authenticate_server_with_credentials(&username, &password, true) {
73+
return Err(EnterpriseCheckoutError::NotAuthenticated);
74+
}
75+
// Otherwise, if the creds worked, we got auth
76+
break 'auth;
77+
}
78+
}
79+
80+
let token = std::env::var("BN_ENTERPRISE_TOKEN");
81+
if let Ok(token) = token {
82+
if !authenticate_server_with_token(&token, true) {
83+
return Err(EnterpriseCheckoutError::NotAuthenticated);
84+
}
85+
break 'auth;
7186
}
87+
88+
// If we're still here, we don't have any credentials for authentication.
89+
return Err(EnterpriseCheckoutError::NoCredentials);
7290
}
7391
}
7492
}
@@ -183,6 +201,16 @@ pub fn is_server_license_still_activated() -> bool {
183201
unsafe { binaryninjacore_sys::BNIsEnterpriseServerLicenseStillActivated() }
184202
}
185203

204+
pub fn authenticate_server_with_token(token: &str, remember: bool) -> bool {
205+
let token = token.to_cstr();
206+
unsafe {
207+
binaryninjacore_sys::BNAuthenticateEnterpriseServerWithToken(
208+
token.as_ref().as_ptr() as *const std::os::raw::c_char,
209+
remember,
210+
)
211+
}
212+
}
213+
186214
pub fn authenticate_server_with_credentials(
187215
username: &str,
188216
password: &str,

0 commit comments

Comments
 (0)