feat: add group configuration (+)
will only check users of such group also cleaned some code: - Input doesn't need to be UTF-8 valid. - Main fuction is dead-simple, very readable. - Added some modularity. - Add some docs on behavior details.
This commit is contained in:
+31
-4
@@ -1,20 +1,25 @@
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
ffi::{CStr, CString, OsStr},
|
||||
fs::File,
|
||||
io::{self},
|
||||
os::unix::ffi::OsStrExt as _,
|
||||
};
|
||||
|
||||
use curl::easy::{Easy, List};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{ext::CStrExt as _, libc as mylibc};
|
||||
|
||||
mod api;
|
||||
|
||||
#[allow(clippy::unsafe_derive_deserialize)] // seriously? -_-
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct KeycloakAPI {
|
||||
base_url: String,
|
||||
default_realm: String,
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
unix_group: CString,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
@@ -68,13 +73,35 @@ impl KeycloakAPI {
|
||||
Ok(serde_json::from_reader(f)?)
|
||||
}
|
||||
|
||||
pub fn check_credentials(&self, username: &str, password: &str) -> Result<(), LoginError> {
|
||||
pub fn should_skip(&self, username: &OsStr) -> Result<bool, mylibc::GetgrnamError> {
|
||||
mylibc::getgrnam_use(&self.unix_group, |group| {
|
||||
let mut members_ptr = group.gr_mem;
|
||||
|
||||
// SAFETY: The array pointer CANNOT be null, even if incremented.
|
||||
while let member_cstr_ptr = unsafe { *members_ptr }
|
||||
&& !member_cstr_ptr.is_null()
|
||||
{
|
||||
// SAFETY: its guaranteed to be a CStr and its non-null
|
||||
let member_osstr = unsafe { CStr::from_ptr(member_cstr_ptr) }.to_os_str();
|
||||
if member_osstr == username {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SAFETY: if current pointer wasn't NULL, we can increase to the next one
|
||||
members_ptr = unsafe { members_ptr.add(1) };
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
pub fn check_credentials(&self, username: &OsStr, password: &OsStr) -> Result<(), LoginError> {
|
||||
let body = format!(
|
||||
"grant_type=password&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&username={USERNAME}&password={PASSWORD}",
|
||||
CLIENT_ID = urlencoding::encode(&self.client_id),
|
||||
CLIENT_SECRET = urlencoding::encode(&self.client_secret),
|
||||
USERNAME = urlencoding::encode(username),
|
||||
PASSWORD = urlencoding::encode(password),
|
||||
USERNAME = urlencoding::encode_binary(username.as_bytes()),
|
||||
PASSWORD = urlencoding::encode_binary(password.as_bytes()),
|
||||
);
|
||||
|
||||
let (status_code, body) = curl_request(
|
||||
|
||||
Reference in New Issue
Block a user