use anyhow::Result;
use bytes::{Buf, BytesMut};
use std::{ops::Deref, time::Duration};
#[macro_use]
extern crate bitflags;
pub trait K5Ctx {
type Buffer: Deref<Target = [u8]> + Send + Sync;
type IOVBuffer: Buf + Send + Sync;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer>;
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer>;
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer>;
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut>;
fn ttl(&mut self) -> Result<Duration>;
}
pub trait K5ServerCtx: K5Ctx {
fn client(&mut self) -> Result<String>;
}
#[cfg(unix)]
mod unix;
#[cfg(unix)]
use crate::unix::{
ClientCtx as ClientCtxImpl, PendingClientCtx as PendingClientCtxImpl,
PendingServerCtx as PendingServerCtxImpl, ServerCtx as ServerCtxImpl,
};
#[cfg(windows)]
mod windows;
#[cfg(windows)]
use crate::windows::{
ClientCtx as ClientCtxImpl, PendingClientCtx as PendingClientCtxImpl,
PendingServerCtx as PendingServerCtxImpl, ServerCtx as ServerCtxImpl,
};
pub enum Step<C, T> {
Finished(C),
Continue(T),
}
pub struct PendingClientCtx(PendingClientCtxImpl);
impl PendingClientCtx {
pub fn step(
self,
token: &[u8],
) -> Result<
Step<
(ClientCtx, Option<impl Deref<Target = [u8]>>),
(PendingClientCtx, impl Deref<Target = [u8]>),
>,
> {
Ok(match self.0.step(token)? {
Step::Finished((ctx, tok)) => {
Step::Finished((ClientCtx(ctx), tok))
}
Step::Continue((ctx, tok)) => {
Step::Continue((PendingClientCtx(ctx), tok))
}
})
}
}
bitflags! {
pub struct InitiateFlags: u32 {
const NEGOTIATE_TOKEN = 0x1;
}
}
#[derive(Debug)]
pub struct ClientCtx(ClientCtxImpl);
impl ClientCtx {
pub fn new(
flags: InitiateFlags,
principal: Option<&str>,
target_principal: &str,
channel_bindings: Option<&[u8]>,
) -> Result<(PendingClientCtx, impl Deref<Target = [u8]>)> {
let (pending, token) =
ClientCtxImpl::new(flags, principal, target_principal, channel_bindings)?;
Ok((PendingClientCtx(pending), token))
}
}
impl K5Ctx for ClientCtx {
type Buffer = <ClientCtxImpl as K5Ctx>::Buffer;
type IOVBuffer = <ClientCtxImpl as K5Ctx>::IOVBuffer;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::wrap(&mut self.0, encrypt, msg)
}
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer> {
K5Ctx::wrap_iov(&mut self.0, encrypt, msg)
}
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::unwrap(&mut self.0, msg)
}
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut> {
K5Ctx::unwrap_iov(&mut self.0, len, msg)
}
fn ttl(&mut self) -> Result<Duration> {
K5Ctx::ttl(&mut self.0)
}
}
bitflags! {
pub struct AcceptFlags: u32 {
const NEGOTIATE_TOKEN = 0x1;
}
}
pub struct PendingServerCtx(PendingServerCtxImpl);
impl PendingServerCtx {
pub fn step(
self,
token: &[u8],
) -> Result<
Step<
(ServerCtx, Option<impl Deref<Target = [u8]>>),
(PendingServerCtx, impl Deref<Target = [u8]>),
>,
> {
Ok(match self.0.step(token)? {
Step::Finished((ctx, tok)) => {
Step::Finished((ServerCtx(ctx), tok))
}
Step::Continue((ctx, tok)) => {
Step::Continue((PendingServerCtx(ctx), tok))
}
})
}
}
#[derive(Debug)]
pub struct ServerCtx(ServerCtxImpl);
impl ServerCtx {
pub fn new(flags: AcceptFlags, principal: Option<&str>) -> Result<PendingServerCtx> {
Ok(PendingServerCtx(ServerCtxImpl::new(flags, principal)?))
}
}
impl K5Ctx for ServerCtx {
type Buffer = <ServerCtxImpl as K5Ctx>::Buffer;
type IOVBuffer = <ServerCtxImpl as K5Ctx>::IOVBuffer;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::wrap(&mut self.0, encrypt, msg)
}
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer> {
K5Ctx::wrap_iov(&mut self.0, encrypt, msg)
}
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::unwrap(&mut self.0, msg)
}
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut> {
K5Ctx::unwrap_iov(&mut self.0, len, msg)
}
fn ttl(&mut self) -> Result<Duration> {
K5Ctx::ttl(&mut self.0)
}
}
impl K5ServerCtx for ServerCtx {
fn client(&mut self) -> Result<String> {
K5ServerCtx::client(&mut self.0)
}
}