awol2005ex_kinit 0.0.1

Kerberos authentication using password or keytab
Documentation
// Copyright 2024 awol2005ex
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Keytab file handling

use awol2005ex_kerberos_keytab::Keytab;
use awol2005ex_kerberos_crypto::Key;
use std::fs;
use std::error::Error;

/// Load a keytab file and find the entry for the specified principal
pub fn load_key_from_keytab(keytab_path: &str, principal: &str) -> Result<Key, Box<dyn Error>> {
    let keytab_data = fs::read(keytab_path)?;
    let keytab = Keytab::parse(&keytab_data)
        .map_err(|e| format!("Failed to parse keytab: {:?}", e))?
        .1;

    // Find the entry matching the principal
    for entry in keytab.entries {
        let realm_str: String = entry.realm.try_into()?;
        let components: Vec<String> = entry.components
            .into_iter()
            .map(|c| String::from_utf8(c.data))
            .collect::<Result<Vec<_>, _>>()?;
        
        let principal_str = format!("{}@{}", components.join("/"), realm_str);
        
        if principal_str == principal {
            // Convert keyvalue to hex string
            let key_hex = hex::encode(&entry.key.keyvalue);
            
            // Create key based on keytype
            match entry.key.keytype {
                23 => return Ok(Key::from_rc4_key_string(&key_hex)?), // RC4-HMAC
                17 => return Ok(Key::from_aes_128_key_string(&key_hex)?), // AES128
                18 => return Ok(Key::from_aes_256_key_string(&key_hex)?), // AES256
                _ => return Err(format!("Unsupported key type: {}", entry.key.keytype).into()),
            }
        }
    }
    
    Err(format!("Principal {} not found in keytab", principal).into())
}