# ExKrb5
Elixir bindings to macOS Kerberos via Apple's GSS.framework.
The first Elixir library that provides native macOS Kerberos integration,
using the same Apple APIs as Jamf's NoMAD. Tickets are stored in the system
KCM credential cache, visible to Finder, Safari, and all other macOS apps.
## Features
- **`kinit`** — Acquire a TGT using a password via `gss_aapl_initial_cred()`
- **`change_password`** — Change AD/Kerberos password via `gss_aapl_change_password()`
- **`list_credentials`** — Enumerate cached tickets via `gss_iter_creds()`
- **`credential_info`** — Check ticket expiry and status
- **`hold`/`unhold`** — Pin/unpin credentials for auto-renewal by GSSCred daemon
- **`destroy`** — Remove tickets from cache
- **`init_sec_context`** — Generate SPNEGO tokens for HTTP Negotiate auth, SMB, etc.
## Why GSS.framework?
On macOS, the Kerberos credential cache is managed by the `GSSCred` daemon via
Mach IPC (the "KCM" cache type). Unlike shelling out to `kinit`, using
GSS.framework directly means:
- Tickets are in the system cache — `klist` shows them
- Finder can use the TGT to mount SMB shares
- Safari can use the TGT for SPNEGO/Negotiate authentication
- The GSSCred daemon handles automatic renewal
- No password ever touches a pipe or command line argument
## Installation
```elixir
def deps do
[{:ex_krb5, "~> 0.1.0"}]
end
```
**Requirements:** macOS only. Requires Rust toolchain for compilation.
## Usage
```elixir
# Authenticate
:ok = ExKrb5.kinit("user@CORP.EXAMPLE.COM", "password123")
# Check ticket
true = ExKrb5.has_valid_tgt?("user@CORP.EXAMPLE.COM")
36000 = ExKrb5.time_remaining("user@CORP.EXAMPLE.COM")
# List all cached tickets
{:ok, creds} = ExKrb5.list_credentials()
# Pin for auto-renewal
:ok = ExKrb5.hold("user@CORP.EXAMPLE.COM")
# Generate SPNEGO token for HTTP
{:ok, token} = ExKrb5.init_sec_context("user@CORP.EXAMPLE.COM", "HTTP/intranet.corp.example.com")
header = "Negotiate " <> Base.encode64(token)
# Change password
:ok = ExKrb5.change_password("user@CORP.EXAMPLE.COM", "old_pass", "new_pass")
# Cleanup
:ok = ExKrb5.destroy("user@CORP.EXAMPLE.COM")
```
## How It Works
```
ExKrb5 (Elixir)
↓ Rustler NIF
Rust FFI (extern "C")
↓ Framework linking
GSS.framework (Apple public API)
↓ Mach IPC
GSSCred daemon (manages KCM credential cache)
↓ Heimdal
KDC (Active Directory, MIT Kerberos, etc.)
```
## Related Libraries
- [`ex_keychain`](https://github.com/yourusername/ex_keychain) — macOS Keychain integration
- [`ex_open_directory`](https://github.com/yourusername/ex_open_directory) — macOS OpenDirectory (AD/LDAP)
- [`ex_local_auth`](https://github.com/yourusername/ex_local_auth) — Touch ID / biometric authentication
Together these libraries form the foundation for building a NoMAD-like
authentication agent in Elixir.
## License
MIT