1 /// Command-line parser for sq.
2 ///
3 /// If you change this file, please rebuild `sq`, run `make -C tool
4 /// update-usage`, and commit the resulting changes to
5 /// `tool/src/sq-usage.rs`.
6
7 use clap::{App, Arg, ArgGroup, SubCommand, AppSettings};
8
build() -> App<'static, 'static>9 pub fn build() -> App<'static, 'static> {
10 App::new("sq")
11 .version(env!("CARGO_PKG_VERSION"))
12 .about("Sequoia is an implementation of OpenPGP. This is a command-line frontend.")
13 .setting(AppSettings::SubcommandRequiredElseHelp)
14 .arg(Arg::with_name("home").value_name("DIRECTORY")
15 .long("home")
16 .help("Sets the home directory to use"))
17 .arg(Arg::with_name("mapping").value_name("MAPPING")
18 .long("mapping")
19 .short("m")
20 .default_value("org.sequoia-pgp.contacts/default")
21 .help("Sets the realm and mapping to use"))
22 .arg(Arg::with_name("policy").value_name("NETWORK-POLICY")
23 .long("policy")
24 .short("p")
25 .help("Sets the network policy to use"))
26 .arg(Arg::with_name("force")
27 .long("force")
28 .short("f")
29 .help("Overwrite existing files"))
30 .arg(Arg::with_name("known-notation")
31 .long("known-notation")
32 .multiple(true)
33 .takes_value(true)
34 .value_name("NOTATION")
35 .number_of_values(1)
36 .help("The notation name is considered known. \
37 This is used when validating sigantures. \
38 Signatures that have unknown notations with the \
39 critical bit set are considered invalid."))
40 .subcommand(SubCommand::with_name("decrypt")
41 .display_order(10)
42 .about("Decrypts an OpenPGP message")
43 .arg(Arg::with_name("input").value_name("FILE")
44 .help("Sets the input file to use"))
45 .arg(Arg::with_name("output").value_name("FILE")
46 .long("output")
47 .short("o")
48 .help("Sets the output file to use"))
49 .arg(Arg::with_name("signatures").value_name("N")
50 .help("The number of valid signatures required. \
51 Default: 0")
52 .long("signatures")
53 .short("n")
54 .takes_value(true))
55 .arg(Arg::with_name("sender-cert-file")
56 .long("sender-cert-file")
57 .multiple(true)
58 .takes_value(true)
59 .value_name("CERT-FILE")
60 .number_of_values(1)
61 .help("The sender's certificate verify signatures \
62 with, given as a file \
63 (can be given multiple times)"))
64 .arg(Arg::with_name("secret-key-file")
65 .long("secret-key-file")
66 .multiple(true)
67 .takes_value(true)
68 .value_name("TSK-FILE")
69 .number_of_values(1)
70 .help("Secret key to decrypt with, given as a file \
71 (can be given multiple times)"))
72 .arg(Arg::with_name("dump-session-key")
73 .long("dump-session-key")
74 .help("Prints the session key to stderr"))
75 .arg(Arg::with_name("dump")
76 .long("dump")
77 .help("Print a packet dump to stderr"))
78 .arg(Arg::with_name("hex")
79 .long("hex")
80 .short("x")
81 .help("Print a hexdump (implies --dump)")))
82 .subcommand(SubCommand::with_name("encrypt")
83 .display_order(20)
84 .about("Encrypts a message")
85 .arg(Arg::with_name("input").value_name("FILE")
86 .help("Sets the input file to use"))
87 .arg(Arg::with_name("output").value_name("FILE")
88 .long("output")
89 .short("o")
90 .help("Sets the output file to use"))
91 .arg(Arg::with_name("binary")
92 .long("binary")
93 .short("B")
94 .help("Don't ASCII-armor encode the OpenPGP data"))
95 .arg(Arg::with_name("recipient")
96 .long("recipient")
97 .short("r")
98 .multiple(true)
99 .takes_value(true)
100 .value_name("LABEL")
101 .number_of_values(1)
102 .help("Recipient to encrypt for \
103 (can be given multiple times)"))
104 .arg(Arg::with_name("recipient-key-file")
105 .long("recipient-key-file")
106 .multiple(true)
107 .takes_value(true)
108 .value_name("CERT-FILE")
109 .number_of_values(1)
110 .help("Recipient to encrypt for, given as a file \
111 (can be given multiple times)"))
112 .arg(Arg::with_name("signer-key-file")
113 .long("signer-key-file")
114 .multiple(true)
115 .takes_value(true)
116 .value_name("TSK-FILE")
117 .number_of_values(1)
118 .help("Secret key to sign with, given as a file \
119 (can be given multiple times)"))
120 .arg(Arg::with_name("symmetric")
121 .long("symmetric")
122 .short("s")
123 .multiple(true)
124 .help("Encrypt with a password \
125 (can be given multiple times)"))
126 .arg(Arg::with_name("mode").value_name("MODE")
127 .long("mode")
128 .possible_values(&["transport", "rest", "all"])
129 .default_value("all")
130 .help("Selects what kind of keys are considered for \
131 encryption. Transport select subkeys marked \
132 as suitable for transport encryption, rest \
133 selects those for encrypting data at rest, \
134 and all selects all encryption-capable \
135 subkeys"))
136 .arg(Arg::with_name("compression")
137 .value_name("KIND")
138 .long("compression")
139 .possible_values(&["none", "pad", "zip", "zlib",
140 "bzip2"])
141 .default_value("pad")
142 .help("Selects compression scheme to use"))
143 .arg(Arg::with_name("time").value_name("TIME")
144 .long("time")
145 .short("t")
146 .help("Chooses keys valid at the specified time and \
147 sets the signature's creation time"))
148 )
149
150 .subcommand(SubCommand::with_name("sign")
151 .display_order(25)
152 .about("Signs a message")
153 .arg(Arg::with_name("input").value_name("FILE")
154 .help("Sets the input file to use"))
155 .arg(Arg::with_name("output").value_name("FILE")
156 .long("output")
157 .short("o")
158 .help("Sets the output file to use"))
159 .arg(Arg::with_name("binary")
160 .long("binary")
161 .short("B")
162 .help("Don't ASCII-armor encode the OpenPGP data"))
163 .arg(Arg::with_name("detached")
164 .long("detached")
165 .help("Create a detached signature"))
166 .arg(Arg::with_name("append")
167 .long("append")
168 .short("a")
169 .conflicts_with("notarize")
170 .help("Append signature to existing signature"))
171 .arg(Arg::with_name("notarize")
172 .long("notarize")
173 .short("n")
174 .conflicts_with("append")
175 .help("Signs a message and all existing signatures"))
176 .arg(Arg::with_name("secret-key-file")
177 .long("secret-key-file")
178 .multiple(true)
179 .takes_value(true)
180 .value_name("TSK-FILE")
181 .number_of_values(1)
182 .help("Secret key to sign with, given as a file \
183 (can be given multiple times)"))
184 .arg(Arg::with_name("time").value_name("TIME")
185 .long("time")
186 .short("t")
187 .help("Chooses keys valid at the specified time and \
188 sets the signature's creation time")))
189 .subcommand(SubCommand::with_name("verify")
190 .display_order(26)
191 .about("Verifies a message")
192 .arg(Arg::with_name("input").value_name("FILE")
193 .help("Sets the input file to use"))
194 .arg(Arg::with_name("output").value_name("FILE")
195 .long("output")
196 .short("o")
197 .help("Sets the output file to use"))
198 .arg(Arg::with_name("detached")
199 .long("detached")
200 .takes_value(true)
201 .value_name("SIG-FILE")
202 .help("Verifies a detached signature"))
203 .arg(Arg::with_name("signatures").value_name("N")
204 .help("The number of valid signatures required. \
205 Default: 0")
206 .long("signatures")
207 .short("n")
208 .takes_value(true))
209 .arg(Arg::with_name("sender-cert-file")
210 .long("sender-cert-file")
211 .multiple(true)
212 .takes_value(true)
213 .value_name("CERT-FILE")
214 .number_of_values(1)
215 .help("The sender's certificate verify signatures \
216 with, given as a file \
217 (can be given multiple times)")))
218 .subcommand(SubCommand::with_name("enarmor")
219 .about("Applies ASCII Armor to a file")
220 .arg(Arg::with_name("input").value_name("FILE")
221 .help("Sets the input file to use"))
222 .arg(Arg::with_name("output").value_name("FILE")
223 .long("output")
224 .short("o")
225 .help("Sets the output file to use"))
226 .arg(Arg::with_name("kind")
227 .value_name("KIND")
228 .long("kind")
229 .possible_values(&["message", "publickey", "secretkey",
230 "signature", "file"])
231 .default_value("file")
232 .help("Selects the kind of header line to produce")))
233
234 .subcommand(SubCommand::with_name("dearmor")
235 .about("Removes ASCII Armor from a file")
236 .arg(Arg::with_name("input").value_name("FILE")
237 .help("Sets the input file to use"))
238 .arg(Arg::with_name("output").value_name("FILE")
239 .long("output")
240 .short("o")
241 .help("Sets the output file to use")))
242 .subcommand(SubCommand::with_name("autocrypt")
243 .about("Autocrypt support")
244 .setting(AppSettings::SubcommandRequiredElseHelp)
245 .subcommand(SubCommand::with_name("decode")
246 .about("Converts Autocrypt-encoded keys to \
247 OpenPGP Certificates")
248 .arg(Arg::with_name("input").value_name("FILE")
249 .help("Sets the input file to use"))
250 .arg(Arg::with_name("output").value_name("FILE")
251 .long("output")
252 .short("o")
253 .help("Sets the output file to use")))
254 .subcommand(SubCommand::with_name("encode-sender")
255 .about("Encodes the sender's OpenPGP \
256 Certificates into \
257 an Autocrypt header")
258 .arg(Arg::with_name("input").value_name("FILE")
259 .help("Sets the input file to use"))
260 .arg(Arg::with_name("output").value_name("FILE")
261 .long("output")
262 .short("o")
263 .help("Sets the output file to use"))
264 .arg(Arg::with_name("address")
265 .long("address")
266 .takes_value(true)
267 .help("Select userid to use. \
268 [default: primary userid]"))
269 .arg(Arg::with_name("prefer-encrypt")
270 .long("prefer-encrypt")
271 .possible_values(&["nopreference",
272 "mutual"])
273 .default_value("nopreference")
274 .help("Sets the prefer-encrypt \
275 attribute"))))
276 .subcommand(SubCommand::with_name("inspect")
277 .about("Inspects a sequence of OpenPGP packets")
278 .arg(Arg::with_name("input").value_name("FILE")
279 .help("Sets the input file to use"))
280 .arg(Arg::with_name("keygrips")
281 .long("keygrips")
282 .help("Print keygrips of keys and subkeys"))
283 .arg(Arg::with_name("certifications")
284 .long("certifications")
285 .help("Print third-party certifications")))
286
287 .subcommand(SubCommand::with_name("keyserver")
288 .display_order(40)
289 .about("Interacts with keyservers")
290 .setting(AppSettings::SubcommandRequiredElseHelp)
291 .arg(Arg::with_name("server").value_name("URI")
292 .long("server")
293 .short("s")
294 .help("Sets the keyserver to use"))
295 .subcommand(SubCommand::with_name("get")
296 .about("Retrieves a key")
297 .arg(Arg::with_name("output").value_name("FILE")
298 .long("output")
299 .short("o")
300 .help("Sets the output file to use"))
301 .arg(Arg::with_name("binary")
302 .long("binary")
303 .short("B")
304 .help("Don't ASCII-armor encode the OpenPGP data"))
305 .arg(Arg::with_name("keyid").value_name("KEYID")
306 .required(true)
307 .help("ID of the key to retrieve")))
308 .subcommand(SubCommand::with_name("send")
309 .about("Sends a key")
310 .arg(Arg::with_name("input").value_name("FILE")
311 .help("Sets the input file to use"))))
312 .subcommand(SubCommand::with_name("mapping")
313 .display_order(30)
314 .about("Interacts with key mappings")
315 .setting(AppSettings::SubcommandRequiredElseHelp)
316 .subcommand(SubCommand::with_name("list")
317 .about("Lists keys in the mapping"))
318 .subcommand(SubCommand::with_name("add")
319 .about("Add a key identified by fingerprint")
320 .arg(Arg::with_name("label").value_name("LABEL")
321 .required(true)
322 .help("Label to use"))
323 .arg(Arg::with_name("fingerprint").value_name("FINGERPRINT")
324 .required(true)
325 .help("Key to add")))
326 .subcommand(SubCommand::with_name("import")
327 .about("Imports a key")
328 .arg(Arg::with_name("label").value_name("LABEL")
329 .required(true)
330 .help("Label to use"))
331 .arg(Arg::with_name("input").value_name("FILE")
332 .help("Sets the input file to use")))
333 .subcommand(SubCommand::with_name("export")
334 .about("Exports a key")
335 .arg(Arg::with_name("label").value_name("LABEL")
336 .required(true)
337 .help("Label to use"))
338 .arg(Arg::with_name("output").value_name("FILE")
339 .long("output")
340 .short("o")
341 .help("Sets the output file to use"))
342 .arg(Arg::with_name("binary")
343 .long("binary")
344 .short("B")
345 .help("Don't ASCII-armor encode the OpenPGP data")))
346 .subcommand(SubCommand::with_name("delete")
347 .about("Deletes bindings or mappings")
348 .arg(Arg::with_name("the-mapping")
349 .long("the-mapping")
350 .help("Delete the selected mapping (change with --mapping)"))
351 .arg(Arg::with_name("label")
352 .value_name("LABEL")
353 .help("Delete binding with this label")))
354 .subcommand(SubCommand::with_name("stats")
355 .about("Get stats for the given label")
356 .arg(Arg::with_name("label").value_name("LABEL")
357 .required(true)
358 .help("Label to use")))
359 .subcommand(SubCommand::with_name("log")
360 .about("Lists the keystore log")
361 .arg(Arg::with_name("label")
362 .value_name("LABEL")
363 .help("List messages related to this label"))))
364 .subcommand(SubCommand::with_name("list")
365 .about("Lists key mappings and known keys")
366 .setting(AppSettings::SubcommandRequiredElseHelp)
367 .subcommand(SubCommand::with_name("mappings")
368 .about("Lists key mappings")
369 .arg(Arg::with_name("prefix").value_name("PREFIX")
370 .help("List only mappings with the given realm prefix")))
371 .subcommand(SubCommand::with_name("bindings")
372 .about("Lists all bindings in all key mappings")
373 .arg(Arg::with_name("prefix").value_name("PREFIX")
374 .help("List only bindings from mappings with the given realm prefix")))
375 .subcommand(SubCommand::with_name("keys")
376 .about("Lists all keys in the common key pool"))
377 .subcommand(SubCommand::with_name("log")
378 .about("Lists the server log")))
379 .subcommand(
380 SubCommand::with_name("key")
381 .about("Manipulates keys")
382 .setting(AppSettings::SubcommandRequiredElseHelp)
383 .subcommand(
384 SubCommand::with_name("generate")
385 .about("Generates a new key")
386 .arg(Arg::with_name("userid")
387 .value_name("EMAIL")
388 .long("userid")
389 .short("u")
390 .multiple(true)
391 .number_of_values(1)
392 .takes_value(true)
393 .help("Add userid to the key \
394 (can be given multiple times)"))
395 .arg(Arg::with_name("cipher-suite")
396 .value_name("CIPHER-SUITE")
397 .long("cipher-suite")
398 .short("c")
399 .possible_values(&["rsa3k", "rsa4k", "cv25519"])
400 .default_value("cv25519")
401 .help("Cryptographic algorithms used for the key."))
402 .arg(Arg::with_name("with-password")
403 .long("with-password")
404 .help("Prompt for a password to protect the \
405 generated key with."))
406
407 .group(ArgGroup::with_name("expiration-group")
408 .args(&["expires", "expires-in"]))
409
410 .arg(Arg::with_name("expires")
411 .value_name("TIME")
412 .long("expires")
413 .help("Absolute time When the key should expire, \
414 or 'never'."))
415 .arg(Arg::with_name("expires-in")
416 .value_name("DURATION")
417 .long("expires-in")
418 // Catch negative numbers.
419 .allow_hyphen_values(true)
420 .help("Relative time when the key should expire. \
421 Either 'N[ymwd]', for N years, months, \
422 weeks, or days, or 'never'."))
423
424 .group(ArgGroup::with_name("cap-sign")
425 .args(&["can-sign", "cannot-sign"]))
426 .arg(Arg::with_name("can-sign")
427 .long("can-sign")
428 .help("The key has a signing-capable subkey \
429 (default)"))
430 .arg(Arg::with_name("cannot-sign")
431 .long("cannot-sign")
432 .help("The key will not be able to sign data"))
433
434 .group(ArgGroup::with_name("cap-encrypt")
435 .args(&["can-encrypt", "cannot-encrypt"]))
436 .arg(Arg::with_name("can-encrypt").value_name("PURPOSE")
437 .long("can-encrypt")
438 .possible_values(&["transport", "storage",
439 "universal"])
440 .help("The key has an encryption-capable subkey \
441 (default: universal)"))
442 .arg(Arg::with_name("cannot-encrypt")
443 .long("cannot-encrypt")
444 .help("The key will not be able to encrypt data"))
445
446 .arg(Arg::with_name("export").value_name("OUTFILE")
447 .long("export")
448 .short("e")
449 .help("Exports the key instead of saving it in \
450 the store")
451 .required(true))
452 .arg(Arg::with_name("rev-cert").value_name("FILE or -")
453 .long("rev-cert")
454 .required_if("export", "-")
455 .help("Sets the output file for the revocation \
456 certificate. Default is <OUTFILE>.rev, \
457 mandatory if OUTFILE is '-'."))))
458
459 .subcommand(SubCommand::with_name("packet")
460 .about("OpenPGP Packet manipulation")
461 .setting(AppSettings::SubcommandRequiredElseHelp)
462 .subcommand(SubCommand::with_name("dump")
463 .about("Lists OpenPGP packets")
464 .arg(Arg::with_name("input").value_name("FILE")
465 .help("Sets the input file to use"))
466 .arg(Arg::with_name("output").value_name("FILE")
467 .long("output")
468 .short("o")
469 .help("Sets the output file to use"))
470 .arg(Arg::with_name("session-key")
471 .long("session-key")
472 .takes_value(true)
473 .value_name("SESSION-KEY")
474 .help("Session key to decrypt encryption \
475 containers"))
476 .arg(Arg::with_name("mpis")
477 .long("mpis")
478 .help("Print MPIs"))
479 .arg(Arg::with_name("hex")
480 .long("hex")
481 .short("x")
482 .help("Print a hexdump")))
483
484 .subcommand(SubCommand::with_name("decrypt")
485 .display_order(10)
486 .about("Decrypts an OpenPGP message, dumping \
487 the content of the encryption \
488 container without further processing")
489 .arg(Arg::with_name("input").value_name("FILE")
490 .help("Sets the input file to use"))
491 .arg(Arg::with_name("output").value_name("FILE")
492 .long("output")
493 .short("o")
494 .help("Sets the output file to use"))
495 .arg(Arg::with_name("binary")
496 .long("binary")
497 .short("B")
498 .help("Don't ASCII-armor encode the \
499 OpenPGP data"))
500 .arg(Arg::with_name("secret-key-file")
501 .long("secret-key-file")
502 .multiple(true)
503 .takes_value(true)
504 .value_name("TSK-FILE")
505 .number_of_values(1)
506 .help("Secret key to decrypt with, given \
507 as a file \
508 (can be given multiple times)"))
509 .arg(Arg::with_name("dump-session-key")
510 .long("dump-session-key")
511 .help("Prints the session key to stderr")))
512
513 .subcommand(SubCommand::with_name("split")
514 .about("Splits a message into OpenPGP packets")
515 .arg(Arg::with_name("input").value_name("FILE")
516 .help("Sets the input file to use"))
517 .arg(Arg::with_name("prefix").value_name("FILE")
518 .long("prefix")
519 .short("p")
520 .help("Sets the prefix to use for output files \
521 (defaults to the input filename with a dash, \
522 or 'output')")))
523 .subcommand(SubCommand::with_name("join")
524 .about("Joins OpenPGP packets split across \
525 files")
526 .arg(Arg::with_name("input").value_name("FILE")
527 .multiple(true)
528 .help("Sets the input files to use"))
529 .arg(Arg::with_name("output").value_name("FILE")
530 .long("output")
531 .short("o")
532 .help("Sets the output file to use"))
533 .arg(Arg::with_name("kind")
534 .value_name("KIND")
535 .long("kind")
536 .possible_values(&["message", "publickey",
537 "secretkey",
538 "signature", "file"])
539 .default_value("file")
540 .help("Selects the kind of header line to \
541 produce"))
542 .arg(Arg::with_name("binary")
543 .long("binary")
544 .short("B")
545 .help("Don't ASCII-armor encode the \
546 OpenPGP data"))))
547
548 .subcommand(SubCommand::with_name("wkd")
549 .about("Interacts with Web Key Directories")
550 .setting(AppSettings::SubcommandRequiredElseHelp)
551 .subcommand(SubCommand::with_name("url")
552 .about("Prints the Web Key Directory URL of \
553 an email address.")
554 .arg(Arg::with_name("input")
555 .value_name("EMAIL_ADDRESS")
556 .required(true)
557 .help("The email address from which to \
558 obtain the WKD URI.")))
559 .subcommand(SubCommand::with_name("get")
560 .about("Writes to the standard output the \
561 Cert retrieved \
562 from a Web Key Directory, given an \
563 email address")
564 .arg(Arg::with_name("input")
565 .value_name("EMAIL_ADDRESS")
566 .required(true)
567 .help("The email address from which to \
568 obtain the Cert from a WKD."))
569 .arg(Arg::with_name("binary")
570 .long("binary")
571 .short("B")
572 .help("Don't ASCII-armor encode the OpenPGP data")))
573 .subcommand(SubCommand::with_name("generate")
574 .about("Generates a Web Key Directory \
575 for the given domain and keys. \
576 If the WKD exists, the new \
577 keys will be inserted and it \
578 is updated and existing ones \
579 will be updated.")
580 .arg(Arg::with_name("base_directory")
581 .value_name("WEB-ROOT")
582 .required(true)
583 .help("The location to write the WKD to. \
584 This must be the directory the \
585 webserver is serving the \
586 '.well-known' directory from."))
587 .arg(Arg::with_name("domain")
588 .value_name("DOMAIN")
589 .help("The domain for the WKD.")
590 .required(true))
591 .arg(Arg::with_name("input")
592 .value_name("KEYRING")
593 .help("The keyring file with the keys to add to the WKD."))
594 .arg(Arg::with_name("direct_method")
595 .long("direct_method")
596 .short("d")
597 .help("Use the direct method. \
598 [default: advanced method]"))
599 )
600 )
601 }
602