use super::senders::send_recv_as;
use crate::{
communication::KrbChannel,
core::{
forge::{build_as_req, extract_krb_cred_from_as_rep, KrbUser},
Cipher, TicketCred,
},
error::Error,
error::Result,
};
use kerberos_asn1::{AsRep, Asn1Object, EtypeInfo2, PaData};
use kerberos_crypto::Key;
pub fn request_tgt(user: KrbUser, user_key: &Key, etype: Option<i32>, channel: &dyn KrbChannel) -> Result<TicketCred>
{
let mut cipher = Cipher::generate(user_key, &user, etype, None);
let rep = match request_as_rep(user.clone(), Some(&cipher), None, channel)
{
Ok(r) => r,
Err(Error::KrbError(e)) =>
{
let match_e = e.clone();
match match_e.e_data
{
Some(data) =>
{
let (_, raw_data) = data.split_at(2);
let pa_data = match PaData::parse(raw_data)
{
Ok((_, d)) => d,
Err(e) => return Err(Error::String(format!("{}", e))),
};
match pa_data.padata_type
{
19 =>
{
let etype_info_2_entries = match EtypeInfo2::parse(&pa_data.padata_value)
{
Ok((_, d)) => d,
Err(e) => return Err(Error::String(format!("{}", e))),
};
let mut salt: String = "".to_string();
for entry in etype_info_2_entries
{
if let Some(s) = entry.salt
{
salt = s;
break;
}
}
cipher = Cipher::generate(user_key, &user, None, Some(salt.as_bytes().to_vec()));
request_as_rep(user.clone(), Some(&cipher), None, channel)?
},
_ => return Err(Error::KrbError(e)),
}
},
None => return Err(Error::KrbError(e)),
}
},
Err(e) => return Err(e),
};
extract_krb_cred_from_as_rep(rep, &cipher)
}
pub fn request_as_rep(user: KrbUser,
cipher: Option<&Cipher>,
etypes: Option<Vec<i32>>,
channel: &dyn KrbChannel)
-> Result<AsRep>
{
let as_req = build_as_req(user, cipher, etypes);
send_recv_as(channel, &as_req)
}