Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kadmin: policies: add tl_data #59

Merged
merged 3 commits into from
Dec 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions kadmin/src/kadmin.rs
Original file line number Diff line number Diff line change
@@ -276,16 +276,17 @@ impl KAdminImpl for KAdmin {
}

fn add_policy(&self, builder: &PolicyBuilder) -> Result<()> {
let (mut policy, mask, _guard) = builder.make_entry()?;
let mask = mask | KADM5_POLICY as i64;
let code = unsafe { kadm5_create_policy(self.server_handle, &mut policy, mask) };
let mut entry = unsafe { builder.make_entry() }?;
let mask = builder.mask | KADM5_POLICY as i64;
let code = unsafe { kadm5_create_policy(self.server_handle, &mut entry.raw, mask) };
kadm5_ret_t_escape_hatch(&self.context, code)?;
Ok(())
}

fn modify_policy(&self, modifier: &PolicyModifier) -> Result<()> {
let (mut policy, mask, _guard) = modifier.make_entry()?;
let code = unsafe { kadm5_modify_policy(self.server_handle, &mut policy, mask) };
let mut entry = unsafe { modifier.make_entry() }?;
let code =
unsafe { kadm5_modify_policy(self.server_handle, &mut entry.raw, modifier.mask) };
kadm5_ret_t_escape_hatch(&self.context, code)?;
Ok(())
}
3 changes: 3 additions & 0 deletions kadmin/src/lib.rs
Original file line number Diff line number Diff line change
@@ -63,6 +63,9 @@ pub use params::Params;
pub mod db_args;
pub use db_args::DbArgs;

pub mod tl_data;
pub use tl_data::{TlData, TlDataEntry};

pub mod kadmin;
pub use kadmin::{KAdmin, KAdminImpl};

66 changes: 61 additions & 5 deletions kadmin/src/policy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! kadm5 policy
use std::{ffi::CString, time::Duration};
use std::{ffi::CString, ptr::null_mut, time::Duration};

use getset::{CopyGetters, Getters};
use kadmin_sys::*;
@@ -8,6 +8,7 @@ use crate::{
conv::{c_string_to_string, delta_to_dur, dur_to_delta},
error::Result,
kadmin::KAdminImpl,
tl_data::{TlData, TlDataEntry, TlDataRaw},
};

/// A kadm5 policy
@@ -50,8 +51,10 @@ pub struct Policy {
max_life: Option<Duration>,
/// Maximum renewable ticket life
max_renewable_life: Option<Duration>,
/// TL-data
#[getset(skip)]
tl_data: TlData,
// TODO: allowed keysalts
// TODO: tldata
}

impl Policy {
@@ -71,6 +74,7 @@ impl Policy {
attributes: entry.attributes,
max_life: delta_to_dur(entry.max_life.into()),
max_renewable_life: delta_to_dur(entry.max_renewable_life.into()),
tl_data: TlData::from_raw(entry.n_tl_data, entry.tl_data),
})
}

@@ -79,6 +83,11 @@ impl Policy {
&self.name
}

/// TL-data
pub fn tl_data(&self) -> &TlData {
&self.tl_data
}

/// Construct a new [`PolicyBuilder`] for a policy with `name`
///
/// ```no_run
@@ -151,8 +160,8 @@ macro_rules! policy_doer_struct {
pub(crate) attributes: Option<i32>,
pub(crate) max_life: Option<Option<Duration>>,
pub(crate) max_renewable_life: Option<Option<Duration>>,
pub(crate) tl_data: TlData,
// TODO: allowed keysalts
// TODO: tldata
$($manual_fields)*
}
}
@@ -269,10 +278,37 @@ macro_rules! policy_doer_impl {
self
}

/// Override existing TL-data completely
pub fn tl_data(mut self, tl_data: TlData) -> Self {
self.tl_data = tl_data;
self.mask |= KADM5_POLICY_TL_DATA as i64;
self
}

/// Add a TL-data entry
pub fn tl_data_push(mut self, entry: TlDataEntry) -> Self {
self.tl_data.entries.push(entry);
self.mask |= KADM5_POLICY_TL_DATA as i64;
self
}

/// Remove the TL-data at `index`
pub fn tl_data_remove(mut self, index: usize) -> Self {
self.tl_data.entries.remove(index);
self.mask |= KADM5_POLICY_TL_DATA as i64;
self
}

/// Create a [`_kadm5_policy_ent_t`] from this builder
pub(crate) fn make_entry(&self) -> Result<(_kadm5_policy_ent_t, i64, CString)> {
///
/// # Safety
///
/// The element in the second position of the returned tuple needs to live as long as
/// [`_krb5_tl_data`] lives
pub(crate) unsafe fn make_entry(&self) -> Result<PolicyEntryRaw> {
let mut policy = _kadm5_policy_ent_t::default();
let name = CString::new(self.name.clone())?;
let tl_data = None;
policy.policy = name.as_ptr().cast_mut();
if let Some(password_min_life) = self.password_min_life {
policy.pw_min_life = dur_to_delta(password_min_life)?.into();
@@ -307,7 +343,21 @@ macro_rules! policy_doer_impl {
if let Some(max_renewable_life) = self.max_renewable_life {
policy.max_renewable_life = dur_to_delta(max_renewable_life)?;
}
Ok((policy, self.mask, name))
if self.mask & (KADM5_POLICY_TL_DATA as i64) != 0 {
let tl_data = self.tl_data.to_raw();
if let Some(mut tl_data) = tl_data {
policy.n_tl_data = self.tl_data.entries.len() as i16;
policy.tl_data = &mut tl_data.raw;
} else {
policy.n_tl_data = 0;
policy.tl_data = null_mut();
}
}
Ok(PolicyEntryRaw {
raw: policy,
_raw_name: name,
_raw_tl_data: tl_data,
})
}
};
}
@@ -394,3 +444,9 @@ impl PolicyModifier {
Ok(kadmin.get_policy(&self.name)?.unwrap())
}
}

pub(crate) struct PolicyEntryRaw {
pub(crate) raw: _kadm5_policy_ent_t,
_raw_name: CString,
_raw_tl_data: Option<TlDataRaw>,
}
94 changes: 94 additions & 0 deletions kadmin/src/tl_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//! Kadm5 [`TlData`]

use std::ptr::null_mut;

use kadmin_sys::*;

/// A single TL-data entry
#[derive(Clone, Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct TlDataEntry {
/// TL-data type
pub data_type: i16,
/// Entry contents
pub contents: Vec<u8>,
}

/// TL-data entries
#[derive(Clone, Debug, Default)]
#[allow(clippy::exhaustive_structs)]
pub struct TlData {
/// TL-data entries
pub entries: Vec<TlDataEntry>,
}

impl TlData {
/// Create a [`TlData`] from [`_krb5_tl_data`]
pub(crate) fn from_raw(n_tl_data: i16, mut tl_data: *mut _krb5_tl_data) -> Self {
let mut entries = Vec::with_capacity(n_tl_data as usize);

while !tl_data.is_null() {
// We've checked above that the pointer is not null
let data_type = unsafe { (*tl_data).tl_data_type };
let contents_length = unsafe { (*tl_data).tl_data_length };
let contents = unsafe {
std::slice::from_raw_parts((*tl_data).tl_data_contents, contents_length.into())
}
.to_vec();
entries.push(TlDataEntry {
data_type,
contents,
});
tl_data = unsafe { (*tl_data).tl_data_next };
}

Self { entries }
}

/// Create a [`_krb5_tl_data`] from [`TlData`]
///
/// Returns None if there are not TL-data.
///
/// # Safety
///
/// The element in the second position of the returned tuple needs to live as long as
/// [`_krb5_tl_data`] lives
pub(crate) unsafe fn to_raw(&self) -> Option<TlDataRaw> {
if self.entries.is_empty() {
return None;
}

let mut raw_contents = Vec::new();
let mut raw_entries: Vec<_> = self
.entries
.iter()
.map(|entry| {
let contents = entry.contents.clone();
let data = _krb5_tl_data {
tl_data_type: entry.data_type,
tl_data_length: entry.contents.len() as u16,
tl_data_contents: contents.as_ptr().cast_mut(),
tl_data_next: null_mut(),
};
raw_contents.push(contents);
data
})
.collect();

for i in 1..raw_entries.len() {
raw_entries[i - 1].tl_data_next = &mut raw_entries[i];
}

Some(TlDataRaw {
raw: raw_entries[0],
_raw_entries: raw_entries,
_raw_contents: raw_contents,
})
}
}

pub(crate) struct TlDataRaw {
pub(crate) raw: _krb5_tl_data,
pub(crate) _raw_entries: Vec<_krb5_tl_data>,
pub(crate) _raw_contents: Vec<Vec<u8>>,
}
19 changes: 15 additions & 4 deletions python-kadmin-rs/python/kadmin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from kadmin._lib import KAdmin, Policy, Principal, Params, DbArgs, __version__
from kadmin._lib import (
DbArgs,
KAdmin,
Params,
Policy,
Principal,
TlData,
TlDataEntry,
__version__,
)

__all__ = (
"__version__",
"DbArgs",
"KAdmin",
"Params",
"Policy",
"Principal",
"Params",
"DbArgs",
"TlData",
"TlDataEntry",
"__version__",
)
10 changes: 10 additions & 0 deletions python-kadmin-rs/python/kadmin/__init__.pyi
Original file line number Diff line number Diff line change
@@ -58,6 +58,7 @@ class Policy:
attributes: int
max_life: datetime.timedelta | None
max_renewable_life: datetime.timedelta | None
tl_data: TlData

def modify(self, **kwargs) -> Policy: ...
def delete(self) -> None: ...
@@ -71,3 +72,12 @@ class Params: ...

@final
class DbArgs: ...

@final
class TlDataEntry:
data_type: int
contents: list[int]

@final
class TlData:
entries: list[TlDataEntry]
19 changes: 15 additions & 4 deletions python-kadmin-rs/python/kadmin_local/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
from kadmin_local._lib import KAdmin, Policy, Principal, Params, DbArgs, __version__
from kadmin_local._lib import (
DbArgs,
KAdmin,
Params,
Policy,
Principal,
TlData,
TlDataEntry,
__version__,
)

__all__ = (
"__version__",
"DbArgs",
"KAdmin",
"Params",
"Policy",
"Principal",
"Params",
"DbArgs",
"TlData",
"TlDataEntry",
"__version__",
)
10 changes: 10 additions & 0 deletions python-kadmin-rs/python/kadmin_local/__init__.pyi
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ class Policy:
attributes: int
max_life: datetime.timedelta | None
max_renewable_life: datetime.timedelta | None
tl_data: TlData

def modify(self, **kwargs) -> Policy: ...
def delete(self) -> None: ...
@@ -50,3 +51,12 @@ class Params: ...

@final
class DbArgs: ...

@final
class TlDataEntry:
data_type: int
contents: list[int]

@final
class TlData:
entries: list[TlDataEntry]
Loading