-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathkeyctl.rs
More file actions
133 lines (122 loc) · 3.86 KB
/
keyctl.rs
File metadata and controls
133 lines (122 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Example CLI application that allows you to interact
//! with the Linux kernel keyring from user space.
//!
//! Demo code for the linux_keyutils crate.
use clap::Parser;
use linux_keyutils::{Key, KeyRing, KeyRingIdentifier, KeySerialId};
use linux_keyutils::{KeyPermissionsBuilder, Permission};
use std::error::Error;
use zeroize::Zeroizing;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
#[command(arg_required_else_help(true))]
#[command(subcommand_required(true))]
struct Args {
#[clap(subcommand)]
subcommand: Command,
}
#[derive(clap::Subcommand, Debug, PartialEq)]
#[command(arg_required_else_help(true))]
enum Command {
/// Create a new key
Create {
#[clap(short, long)]
description: String,
#[clap(short, long)]
secret: String,
},
/// Read the secret from a key
Read {
#[clap(short, long)]
description: String,
},
/// Change ownership of a key
Chown {
#[clap(short, long)]
description: String,
#[clap(short, long)]
uid: Option<u32>,
#[clap(short, long)]
gid: Option<u32>,
},
/// Change permissions of a key
Chmod {
#[clap(short, long)]
description: String,
},
/// Invalidate a key
Invalidate {
#[clap(short, long)]
description: String,
},
/// Instantiate a partially constructed key
Instantiate {
#[clap(short, long)]
keyid: Option<i32>,
#[clap(short, long)]
payload: String,
#[clap(short, long)]
ring: Option<i32>,
},
}
fn main() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
// Obtain the default User keyring for the current UID/user
// See [KeyRingIdentifier] and `man 2 keyctl` for more information on default
// keyrings for processes.
let ring = KeyRing::from_special_id(KeyRingIdentifier::Session, false)?;
_ = match args.subcommand {
// Add a new key to the keyring
Command::Create {
description,
secret,
} => {
let key = ring.add_key(&description, &secret)?;
println!("Created key with ID {:?}", key.get_id());
}
// Search for an existing key by description and read the secret
// data from the keyring
Command::Read { description } => {
let key = ring.search(&description)?;
let mut buf = Zeroizing::new([0u8; 2048]);
let len = key.read(&mut buf)?;
println!("Secret {:?}", std::str::from_utf8(&buf[..len])?);
}
// Search for an existing key by description and attempt to
// change ownership of the key
Command::Chown {
description,
uid,
gid,
} => {
let key = ring.search(&description)?;
key.chown(uid, gid)?;
}
// Search for an existing key by description and attempt to
// change permissions of the key
Command::Chmod { description } => {
let key = ring.search(&description)?;
let perms = KeyPermissionsBuilder::builder()
.user(Permission::ALL)
.build();
key.set_perms(perms)?;
}
// Search for an existing key by description and attempt to
// invalidate they key
Command::Invalidate { description } => {
let key = ring.search(&description)?;
key.invalidate()?;
println!("Removed key with ID {:?}", key.get_id());
}
// Instantiate a partially constructed key
Command::Instantiate {
keyid,
payload,
ring,
} => {
let key = Key::from_id(KeySerialId::new(keyid.unwrap_or(i32::MAX)));
key.instantiate(&payload, KeySerialId::new(ring.unwrap_or(i32::MAX)))?;
}
};
Ok(())
}