diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 2d5e2a382..13a9313aa 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -411,7 +411,6 @@ bool NetworkConfig::fromDictionary(const DictionaryissuerURL, (unsigned int)sizeof(this->issuerURL)) > 0) { this->issuerURL[sizeof(this->issuerURL) - 1] = 0; - fprintf(stderr, "Loaded issuer url: %s\n", this->issuerURL); } if (d.get(ZT_NETWORKCONFIG_DICT_KEY_CENTRAL_ENDPOINT_URL, this->centralAuthURL, (unsigned int)sizeof(this->centralAuthURL)) > 0) { this->centralAuthURL[sizeof(this->centralAuthURL) - 1] = 0; diff --git a/service/OneService.cpp b/service/OneService.cpp index 2aeafc4b7..04442ab9b 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -249,23 +249,23 @@ public: void setConfig(const ZT_VirtualNetworkConfig *nwc) { char nwbuf[17] = {}; const char* nwid = Utils::hex(nwc->nwid, nwbuf); - fprintf(stderr, "NetworkState::setConfig(%s)\n", nwid); + // fprintf(stderr, "NetworkState::setConfig(%s)\n", nwid); memcpy(&_config, nwc, sizeof(ZT_VirtualNetworkConfig)); - fprintf(stderr, "ssoEnabled: %s, ssoVersion: %d\n", - _config.ssoEnabled ? "true" : "false", _config.ssoVersion); + // fprintf(stderr, "ssoEnabled: %s, ssoVersion: %d\n", + // _config.ssoEnabled ? "true" : "false", _config.ssoVersion); if (_config.ssoEnabled && _config.ssoVersion == 1) { - fprintf(stderr, "ssoEnabled for %s\n", nwid); + // fprintf(stderr, "ssoEnabled for %s\n", nwid); if (_idc == nullptr) { assert(_config.issuerURL != nullptr); assert(_config.ssoClientID != nullptr); assert(_config.centralAuthURL != nullptr); - fprintf(stderr, "Issuer URL: %s\n", _config.issuerURL); - fprintf(stderr, "Client ID: %s\n", _config.ssoClientID); - fprintf(stderr, "Central Auth URL: %s\n", _config.centralAuthURL); + // fprintf(stderr, "Issuer URL: %s\n", _config.issuerURL); + // fprintf(stderr, "Client ID: %s\n", _config.ssoClientID); + // fprintf(stderr, "Central Auth URL: %s\n", _config.centralAuthURL); char buf[17] = {}; _idc = zeroidc::zeroidc_new( @@ -281,7 +281,7 @@ public: return; } - fprintf(stderr, "idc created (%s, %s, %s)\n", _config.issuerURL, _config.ssoClientID, _config.centralAuthURL); + // fprintf(stderr, "idc created (%s, %s, %s)\n", _config.issuerURL, _config.ssoClientID, _config.centralAuthURL); } if (_ainfo != nullptr) { diff --git a/zeroidc/Cargo.lock b/zeroidc/Cargo.lock index d8c0135f2..2447d8d21 100644 --- a/zeroidc/Cargo.lock +++ b/zeroidc/Cargo.lock @@ -108,7 +108,7 @@ dependencies = [ "num-integer", "num-traits", "serde", - "time", + "time 0.1.43", "winapi", ] @@ -1144,6 +1144,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" +dependencies = [ + "itoa", + "libc", +] + [[package]] name = "tinyvec" version = "1.5.0" @@ -1489,5 +1499,6 @@ dependencies = [ "openidconnect", "reqwest", "serde", + "time 0.3.5", "url", ] diff --git a/zeroidc/Cargo.toml b/zeroidc/Cargo.toml index ae4063425..058564be5 100644 --- a/zeroidc/Cargo.toml +++ b/zeroidc/Cargo.toml @@ -18,6 +18,7 @@ url = "2.2.2" reqwest = "0.11.7" jsonwebtoken = "7.2.0" serde = "1.0.130" +time = { version = "0.3.5", features = ["formatting"] } [build-dependencies] cbindgen = "0.20.0" diff --git a/zeroidc/src/ext.rs b/zeroidc/src/ext.rs index c7a3095d4..f79f0f6f5 100644 --- a/zeroidc/src/ext.rs +++ b/zeroidc/src/ext.rs @@ -1,6 +1,6 @@ use std::ffi::{CStr, CString}; use std::os::raw::c_char; -use url::{Url, ParseError}; +use url::{Url}; use crate::{AuthInfo, ZeroIDC}; @@ -101,23 +101,23 @@ pub extern "C" fn zeroidc_get_exp_time(ptr: *mut ZeroIDC) -> u64 { id.get_exp_time() } -#[no_mangle] -pub extern "C" fn zeroidc_process_form_post(ptr: *mut ZeroIDC, body: *const c_char) -> bool { - let idc = unsafe { - assert!(!ptr.is_null()); - &mut *ptr - }; +// #[no_mangle] +// pub extern "C" fn zeroidc_process_form_post(ptr: *mut ZeroIDC, body: *const c_char) -> bool { +// let idc = unsafe { +// assert!(!ptr.is_null()); +// &mut *ptr +// }; - if body.is_null() { - println!("body is null"); - return false - } +// if body.is_null() { +// println!("body is null"); +// return false +// } - let body = unsafe { CStr::from_ptr(body) } - .to_str().unwrap().to_string(); +// let body = unsafe { CStr::from_ptr(body) } +// .to_str().unwrap().to_string(); - false -} +// false +// } #[no_mangle] pub extern "C" fn zeroidc_get_auth_info( diff --git a/zeroidc/src/lib.rs b/zeroidc/src/lib.rs index 7181f6854..025585566 100644 --- a/zeroidc/src/lib.rs +++ b/zeroidc/src/lib.rs @@ -2,11 +2,13 @@ pub mod ext; extern crate base64; extern crate openidconnect; +extern crate time; extern crate url; +use std::time::{SystemTime, UNIX_EPOCH, Duration}; +use time::{OffsetDateTime, format_description}; use std::sync::{Arc, Mutex}; use std::thread::{sleep, spawn, JoinHandle}; -use std::time::Duration; use serde::{Deserialize, Serialize}; use openidconnect::core::{CoreClient, CoreProviderMetadata, CoreResponseType}; use openidconnect::reqwest::http_client; @@ -50,6 +52,23 @@ pub struct AuthInfo { pkce_verifier: Option, } +fn systemtime_strftime(dt: T, format: &str) -> String + where T: Into +{ + let f = format_description::parse(format); + match f { + Ok(f) => { + match dt.into().format(&f) { + Ok(s) => s, + Err(_e) => "".to_string(), + } + }, + Err(_e) => { + "".to_string() + }, + } +} + impl ZeroIDC { fn new( network_id: &str, @@ -124,10 +143,84 @@ impl ZeroIDC { let inner_local = Arc::clone(&self.inner); (*local.lock().unwrap()).oidc_thread = Some(spawn(move || { (*inner_local.lock().unwrap()).running = true; + let mut running = true; + + while running { + let exp = UNIX_EPOCH + Duration::from_secs((*inner_local.lock().unwrap()).exp_time); + let now = SystemTime::now(); + + println!("refresh token thread tick, now: {}, exp: {}", systemtime_strftime(now, "[year]-[month]-[day] [hour]:[minute]:[second]"), systemtime_strftime(exp, "[year]-[month]-[day] [hour]:[minute]:[second]")); + let refresh_token = (*inner_local.lock().unwrap()).refresh_token.clone(); + if let Some(refresh_token) = refresh_token { + if now >= (exp - Duration::from_secs(15)) { + let token_response = (*inner_local.lock().unwrap()).oidc_client.as_ref().map(|c| { + let res = c.exchange_refresh_token(&refresh_token) + .request(http_client); + + res + + }); + + if let Some(res) = token_response { + if let Ok(res) = res { + let id_token = res.id_token(); + + if let Some(id_token) = id_token { + let params = [("id_token", id_token.to_string()),("state", "refresh".to_string())]; + let client = reqwest::blocking::Client::new(); + let r = client.post((*inner_local.lock().unwrap()).auth_endpoint.clone()) + .form(¶ms) + .send(); + + match r { + Ok(r) => { + if r.status().is_success() { + println!("hit url: {}", r.url().as_str()); + println!("status: {}", r.status()); + + + let access_token = res.access_token(); + let at = access_token.secret(); + let exp = dangerous_insecure_decode::(&at); + + if let Ok(e) = exp { + (*inner_local.lock().unwrap()).exp_time = e.claims.exp + } + + (*inner_local.lock().unwrap()).access_token = Some(access_token.clone()); + if let Some(t) = res.refresh_token() { + println!("New Refresh Token: {}", t.secret()); + (*inner_local.lock().unwrap()).refresh_token = Some(t.clone()); + } + println!("Central post succeeded"); + } else { + println!("Central post failed: {}", r.status().to_string()); + println!("hit url: {}", r.url().as_str()); + println!("Status: {}", r.status()); + (*inner_local.lock().unwrap()).exp_time = 0; + (*inner_local.lock().unwrap()).running = false; + } + }, + Err(e) => { + println!("Central post failed: {}", e.to_string()); + println!("hit url: {}", e.url().unwrap().as_str()); + println!("Status: {}", e.status().unwrap()); + // (*inner_local.lock().unwrap()).exp_time = 0; + (*inner_local.lock().unwrap()).running = false; + } + } + } + } + } + } else { + println!("waiting to refresh"); + } + } else { + println!("no refresh token?"); + } - while (*inner_local.lock().unwrap()).running { - println!("tick"); sleep(Duration::from_secs(1)); + running = (*inner_local.lock().unwrap()).running; } println!("thread done!") @@ -207,12 +300,14 @@ impl ZeroIDC { (*self.inner.lock().unwrap()).access_token = Some(tok.access_token().clone()); if let Some(t) = tok.refresh_token() { (*self.inner.lock().unwrap()).refresh_token = Some(t.clone()); + self.start(); } }, Err(res) => { println!("hit url: {}", res.url().unwrap().as_str()); println!("Status: {}", res.status().unwrap()); println!("Post error: {}", res.to_string()); + (*self.inner.lock().unwrap()).exp_time = 0; } } @@ -246,7 +341,7 @@ impl ZeroIDC { .add_extra_param("network_id", network_id) .url(); - println!("URL: {}", auth_url); + // println!("URL: {}", auth_url); return AuthInfo { url: auth_url,