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
134
135
136
137
138
139
140
use std::path::PathBuf;
use clap::{command, Parser, Subcommand};
#[derive(Parser)]
#[derive(Debug)]
#[command(version, about, long_about = None)]
/// Manage TOTP (e.g. Google Authenticator, etc.) secrets.
pub struct Opts {
#[command(subcommand)]
pub command: Command,
/// Path to global configuration file.
#[arg(short, long)]
pub config: Option<PathBuf>,
/// Print debugging information and non-critical TPM.
#[arg(short, long, default_value = "false")]
pub debug: bool,
}
#[derive(Subcommand)]
#[derive(Debug)]
pub enum Command {
/// Add a new TOTP secret.
Add {
/// Name of the service to add a secret for.
service: String,
/// Username associated with the secret.
account: String,
/// Number of security code digits.
/// Defaults to 6; don't change unless you know what you're doing.
#[arg(short, long)]
digits: Option<u8>,
/// How often to generate a new security code.
/// Defaults to every 30 seconds; don't change unless you know what you're doing.
#[arg(short, long)]
interval: Option<u32>,
/// Read secret from standard input instead of directly from tty.
/// Only use this for non-interactive use cases, to avoid echoing secret to screen.
#[arg(long, default_value = "false")]
secret_on_stdin: bool,
},
/// Delete an existing TOTP secret.
Del {
/// Name of the service to delete secret for.
service: String,
/// Username associated with the secret to delete.
account: String,
},
/// Generate a security code.
Gen {
/// Service to generate security code for.
service: String,
/// Username to generate security code for.
account: Option<String>,
},
/// List all accounts matching the given partial service and account names.
List {
service: Option<String>,
account: Option<String>,
},
/// Batch import secrets from file.
#[cfg(feature = "import")]
Import {
/// JSON file to import secrets from.
/// The file should consist of a single JSON object, mapping service names to secrets as follows:
///
/// {
/// "some_service": {
/// "account": "my_account@example.com",
/// "secret": "...",
/// "digits": 6,
/// "interval": 30
/// }
/// }
///
/// The `digits` and `interval` fields are optional, and will default to 6 and 30 respectively.
file: PathBuf,
},
/// Initialize the TOTP store.
Init {
/// TPM configuration to use.
/// May be either "device", "device:/path/to/tpm", or "swtpm:host=...,port=..."
#[arg(short, long, default_value = "device:/dev/tpmrm0")]
tpm: String,
/// Path to directory where totpm should store system-wide data.
/// The directory is created if it does not exist.
#[arg(short, long)]
system_data_path: Option<PathBuf>,
/// Path to directory where totpm should store user-specific data.
/// If the path is not absolute, it is interpreted relative to
/// each user's home directory.
/// The directory is created if it does not exist.
#[arg(short = 'p', long)]
user_data_path: Option<PathBuf>,
/// User which will own system-wide data files. Will be created if it does not exist.
#[arg(short, long)]
user: Option<String>,
/// Method to use for presence verification.
/// Valid values are `fprintd` and `none`.
/// Defaults to `fprintd` for system install, `none` for local install.
#[arg(short, long)]
presence_verification: Option<String>,
/// Allow user-local installation. A local installation will:
/// - not create a user or install any executables into system paths
/// - create any files and directories as the current user
/// - use user-local defaults for arguments that are not explicitly specified
#[arg(short, long, default_value = "false")]
local: bool,
},
/// Remove all stored TOTP secrets, rendering them unusable.
Clear {
/// Are you REALLY sure?
#[arg(long, default_value = "false")]
yes_i_know_what_i_am_doing: bool,
/// Also delete system-level data, rendering all secrets on this machine unusable.
/// Requires root privileges.
#[arg(short, long, default_value = "false")]
system: bool,
},
}