diff --git a/zeroidc/Cargo.lock b/zeroidc/Cargo.lock index bb202f290..24479eaaf 100644 --- a/zeroidc/Cargo.lock +++ b/zeroidc/Cargo.lock @@ -1325,6 +1325,8 @@ dependencies = [ name = "zeroidc" version = "0.1.0" dependencies = [ + "base64 0.13.0", "cbindgen", "openidconnect", + "url", ] diff --git a/zeroidc/Cargo.toml b/zeroidc/Cargo.toml index 892f8a38e..814a497c5 100644 --- a/zeroidc/Cargo.toml +++ b/zeroidc/Cargo.toml @@ -12,6 +12,8 @@ crate-type = ["staticlib"] [dependencies] openidconnect = "2.1.0" +base64 = "0.13.0" +url = "2.2.2" [build-dependencies] cbindgen = "0.20.0" diff --git a/zeroidc/src/lib.rs b/zeroidc/src/lib.rs index d275a0463..dc94d95ee 100644 --- a/zeroidc/src/lib.rs +++ b/zeroidc/src/lib.rs @@ -1,7 +1,20 @@ +extern crate base64; +extern crate openidconnect; +extern crate url; + use std::sync::{Arc, Mutex}; use std::thread::{sleep, spawn, JoinHandle}; use std::time::Duration; +use openidconnect::core::{CoreClient, CoreProviderMetadata}; +use openidconnect::reqwest::http_client; +use openidconnect::{ClientId, IssuerUrl, RedirectUrl}; + +use url::Url; + +use std::ffi::CStr; +use std::os::raw::c_char; + pub struct ZeroIDC { inner: Arc>, } @@ -9,16 +22,50 @@ pub struct ZeroIDC { struct Inner { running: bool, oidc_thread: Option>, + oidc_client: Option, } impl ZeroIDC { - fn new() -> ZeroIDC { - ZeroIDC { + fn new(issuer: &str, client_id: &str, port: u16) -> Result { + let idc = ZeroIDC { inner: Arc::new(Mutex::new(Inner { running: false, oidc_thread: None, + oidc_client: None, })), - } + }; + + let iss = match IssuerUrl::new(issuer.to_string()) { + Ok(i) => i, + Err(e) => return Err(e.to_string()), + }; + + let provider_meta = match CoreProviderMetadata::discover(&iss, http_client) { + Ok(m) => m, + Err(e) => return Err(e.to_string()), + }; + + let r = format!("http://localhost:{}", port); + let redir_url = match Url::parse(&r) { + Ok(s) => s, + Err(e) => return Err(e.to_string()), + }; + + let redirect = match RedirectUrl::new(redir_url.to_string()) { + Ok(s) => s, + Err(e) => return Err(e.to_string()), + }; + + (*idc.inner.lock().unwrap()).oidc_client = Some( + CoreClient::from_provider_metadata( + provider_meta, + ClientId::new(client_id.to_string()), + None, + ) + .set_redirect_uri(redirect), + ); + + Ok(idc) } fn start(&mut self) { @@ -50,19 +97,59 @@ impl ZeroIDC { } #[no_mangle] -pub extern "C" fn zeroidc_new() -> Box { - Box::new(ZeroIDC::new()) +pub extern "C" fn zeroidc_new( + issuer: *const c_char, + client_id: *const c_char, + web_port: u16, +) -> *mut ZeroIDC { + if issuer.is_null() { + println!("issuer is null"); + return std::ptr::null_mut(); + } + + if client_id.is_null() { + println!("client_id is null"); + return std::ptr::null_mut(); + } + + let iss = unsafe { CStr::from_ptr(issuer) }; + let c_id = unsafe { CStr::from_ptr(client_id) }; + + match ZeroIDC::new(iss.to_str().unwrap(), c_id.to_str().unwrap(), web_port) { + Ok(idc) => { + return Box::into_raw(Box::new(idc)); + } + Err(s) => { + println!("Error creating ZeroIDC instance: {}", s); + return std::ptr::null_mut(); + } + } } #[no_mangle] -pub extern "C" fn zeroidc_delete(_: Option>) {} +pub extern "C" fn zeroidc_delete(ptr: *mut ZeroIDC) { + if ptr.is_null() { + return; + } + unsafe { + Box::from_raw(ptr); + } +} #[no_mangle] -pub extern "C" fn zeroidc_start(idc: &'static mut ZeroIDC) { +pub extern "C" fn zeroidc_start(ptr: *mut ZeroIDC) { + let idc = unsafe { + assert!(!ptr.is_null()); + &mut *ptr + }; idc.start(); } #[no_mangle] -pub extern "C" fn zeroidc_stop(idc: &'static mut ZeroIDC) { +pub extern "C" fn zeroidc_stop(ptr: *mut ZeroIDC) { + let idc = unsafe { + assert!(!ptr.is_null()); + &mut *ptr + }; idc.stop(); }