1use bytes::Bytes;
2use cross_krb5::{AcceptFlags, ClientCtx, InitiateFlags, K5Ctx, ServerCtx, Step};
3use std::{env::args, process::exit, sync::mpsc, thread};
4
5enum Msg {
17 Token(Bytes),
18 Msg(Bytes),
19}
20
21fn server(spn: String, input: mpsc::Receiver<Msg>, output: mpsc::Sender<Msg>) {
22 let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new");
23 let mut server = loop {
24 let token = match input.recv().expect("expected data") {
25 Msg::Msg(_) => panic!("server not finished initializing"),
26 Msg::Token(t) => t,
27 };
28 match server.step(&*token).expect("step") {
29 Step::Finished((ctx, token)) => {
30 if let Some(token) = token {
31 output
32 .send(Msg::Token(Bytes::copy_from_slice(&*token)))
33 .expect("send");
34 }
35 break ctx;
36 }
37 Step::Continue((ctx, token)) => {
38 output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send");
39 server = ctx;
40 }
41 }
42 };
43 match input.recv().expect("expected data msg") {
44 Msg::Token(_) => panic!("unexpected extra token"),
45 Msg::Msg(secret_msg) => println!(
46 "{}",
47 String::from_utf8_lossy(&server.unwrap(&*secret_msg).expect("unwrap"))
48 ),
49 }
50}
51
52fn client(spn: &str, input: mpsc::Receiver<Msg>, output: mpsc::Sender<Msg>) {
53 let (mut client, token) =
54 ClientCtx::new(InitiateFlags::empty(), None, spn, None).expect("new");
55 output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send");
56 let mut client = loop {
57 let token = match input.recv().expect("expected data") {
58 Msg::Msg(_) => panic!("client not finished initializing"),
59 Msg::Token(t) => t,
60 };
61 match client.step(&*token).expect("step") {
62 Step::Finished((ctx, token)) => {
63 if let Some(token) = token {
64 output
65 .send(Msg::Token(Bytes::copy_from_slice(&*token)))
66 .expect("send");
67 }
68 break ctx;
69 }
70 Step::Continue((ctx, token)) => {
71 output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send");
72 client = ctx;
73 }
74 }
75 };
76 let msg = client.wrap(true, b"super secret message").expect("wrap");
77 output.send(Msg::Msg(Bytes::copy_from_slice(&*msg))).expect("send");
78}
79
80fn main() {
81 let args = args().collect::<Vec<_>>();
82 if args.len() != 2 {
83 println!("usage: {}: <service/host@REALM>", args[0]);
84 exit(1);
85 }
86 let spn = String::from(&args[1]);
87 let (server_snd, server_recv) = mpsc::channel();
88 let (client_snd, client_recv) = mpsc::channel();
89 thread::spawn(move || server(spn, server_recv, client_snd));
90 client(&args[1], client_recv, server_snd);
91}