summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2022-06-03 11:59:34 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2022-06-08 14:49:43 +0200
commite87a3b5d869ad1ec22cb18a5792877121214971f (patch)
treec244652c4a7de7ca4a292a870680b1aefeac7882
parent73bd7bf210e28b7385213adf9634d55e3ad31619 (diff)
sq: Derive certify subcommand.
- This is part of the effort of moving to clap3's derive API and profit from the added type safety.
-rw-r--r--sq/src/sq_cli.rs343
1 files changed, 189 insertions, 154 deletions
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index e867d243..aac3e022 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -809,159 +809,6 @@ $ sq keyring merge certs.pgp | sq keyring split
.short('B').long("binary")
.help("Emits binary data"))
)
- )
-
- .subcommand(Command::new("certify")
- .display_order(320)
- .about("Certifies a User ID for a Certificate")
- .long_about(
-"
-Certifies a User ID for a Certificate
-
-Using a certification a keyholder may vouch for the fact that another
-certificate legitimately belongs to a user id. In the context of
-emails this means that the same entity controls the key and the email
-address. These kind of certifications form the basis for the Web Of
-Trust.
-
-This command emits the certificate with the new certification. The
-updated certificate has to be distributed, preferably by sending it to
-the certificate holder for attestation. See also \"sq key
-attest-certification\".
-")
- .after_help(
-"EXAMPLES:
-
-# Juliet certifies that Romeo controls romeo.pgp and romeo@example.org
-$ sq certify juliet.pgp romeo.pgp \"<romeo@example.org>\"
-")
- .arg(Arg::new("output")
- .short('o').long("output").value_name("FILE")
- .help("Writes to FILE or stdout if omitted"))
- .arg(Arg::new("binary")
- .short('B').long("binary")
- .help("Emits binary data"))
- .arg(Arg::new("time")
- .long("time").value_name("TIME")
- .help("Sets the certification time to TIME (as ISO 8601)")
- .long_help("\
-Sets the certification time to TIME. TIME is interpreted as an ISO 8601
-timestamp. To set the certification time to June 9, 2011 at midnight UTC,
-you can do:
-
-$ sq certify --time 20130721 neal.pgp ada.pgp ada
-
-To include a time, add a T, the time and optionally the timezone (the
-default timezone is UTC):
-
-$ sq certify --time 20130721T0550+0200 neal.pgp ada.pgp ada
-"))
- .arg(Arg::new("depth")
- .short('d').long("depth").value_name("TRUST_DEPTH")
- .help("Sets the trust depth")
- .long_help(
- "Sets the trust depth (sometimes referred to as \
- the trust level). 0 means a normal \
- certification of <CERTIFICATE, USERID>. \
- 1 means CERTIFICATE is also a trusted \
- introducer, 2 means CERTIFICATE is a \
- meta-trusted introducer, etc. The \
- default is 0."))
- .arg(Arg::new("amount")
- .short('a').long("amount").value_name("TRUST_AMOUNT")
- .help("Sets the amount of trust")
- .long_help(
- "Sets the amount of trust. \
- Values between 1 and 120 are meaningful. \
- 120 means fully trusted. \
- Values less than 120 indicate the degree \
- of trust. 60 is usually used for partially \
- trusted. The default is 120."))
- .arg(Arg::new("regex")
- .short('r').long("regex").value_name("REGEX")
- .multiple_occurrences(true)
- .help("Adds a regular expression to constrain \
- what a trusted introducer can certify")
- .long_help(
- "Adds a regular expression to constrain \
- what a trusted introducer can certify. \
- The regular expression must match \
- the certified User ID in all intermediate \
- introducers, and the certified certificate. \
- Multiple regular expressions may be \
- specified. In that case, at least \
- one must match."))
- .arg(Arg::new("local")
- .short('l').long("local")
- .help("Makes the certification a local \
- certification")
- .long_help(
- "Makes the certification a local \
- certification. Normally, local \
- certifications are not exported."))
- .arg(Arg::new("non-revocable")
- .long("non-revocable")
- .help("Marks the certification as being non-revocable")
- .long_help(
- "Marks the certification as being non-revocable. \
- That is, you cannot later revoke this \
- certification. This should normally only \
- be used with an expiration."))
- .arg(Arg::new("notation")
- .value_names(&["NAME", "VALUE"])
- .long("notation")
- .multiple_occurrences(true).number_of_values(2)
- .help("Adds a notation to the certification.")
- .long_help(
- "Adds a notation to the certification. \
- A user-defined notation's name must be of \
- the form \"name@a.domain.you.control.org\". \
- If the notation's name starts with a !, \
- then the notation is marked as being \
- critical. If a consumer of a signature \
- doesn't understand a critical notation, \
- then it will ignore the signature. The \
- notation is marked as being human readable."))
-
- .group(ArgGroup::new("expiration-group")
- .args(&["expires", "expires-in"]))
- .arg(Arg::new("expires")
- .long("expires").value_name("TIME")
- .help("Makes the certification expire at TIME (as ISO 8601)")
- .long_help(
- "Makes the certification expire at TIME (as ISO 8601). \
- Use \"never\" to create certifications that do not \
- expire."))
- .arg(Arg::new("expires-in")
- .long("expires-in").value_name("DURATION")
- // Catch negative numbers.
- .allow_hyphen_values(true)
- .help("Makes the certification expire after DURATION \
- (as N[ymwds]) [default: 5y]")
- .long_help(
- "Makes the certification expire after DURATION. \
- Either \"N[ymwds]\", for N years, months, \
- weeks, days, seconds, or \"never\". [default: 5y]"))
-
- .arg(Arg::new("certifier")
- .value_name("CERTIFIER-KEY")
- .required(true)
- .index(1)
- .help("Creates the certification using CERTIFIER-KEY."))
- .arg(Arg::new("private-key-store")
- .long("private-key-store").value_name("KEY_STORE")
- .help("Provides parameters for private key store"))
-
- .arg(Arg::new("certificate")
- .value_name("CERTIFICATE")
- .required(true)
- .index(2)
- .help("Certifies CERTIFICATE."))
- .arg(Arg::new("userid")
- .value_name("USERID")
- .required(true)
- .index(3)
- .help("Certifies USERID for CERTIFICATE."))
);
let app = if ! feature_autocrypt {
@@ -978,7 +825,8 @@ $ sq certify --time 20130721T0550+0200 neal.pgp ada.pgp ada
.subcommand(WkdCommand::command())
.subcommand(KeyserverCommand::command())
.subcommand(RevokeCommand::command())
- .subcommand(PacketCommand::command());
+ .subcommand(PacketCommand::command())
+ .subcommand(CertifyCommand::command());
app
}
@@ -1969,6 +1817,193 @@ pub enum UseridRevocationReason {
#[derive(Parser, Debug)]
#[clap(
+ name = "certify",
+ display_order = 320,
+ about = "Certifies a User ID for a Certificate",
+ long_about = "
+Certifies a User ID for a Certificate
+
+Using a certification a keyholder may vouch for the fact that another
+certificate legitimately belongs to a user id. In the context of
+emails this means that the same entity controls the key and the email
+address. These kind of certifications form the basis for the Web Of
+Trust.
+
+This command emits the certificate with the new certification. The
+updated certificate has to be distributed, preferably by sending it to
+the certificate holder for attestation. See also \"sq key
+attest-certification\".
+",
+ after_help =
+"EXAMPLES:
+
+# Juliet certifies that Romeo controls romeo.pgp and romeo@example.org
+$ sq certify juliet.pgp romeo.pgp \"<romeo@example.org>\"
+",
+)]
+#[clap(group(ArgGroup::new("expiration-group").args(&["expires", "expires-in"])))]
+pub struct CertifyCommand {
+ #[clap(
+ short,
+ long,
+ value_name = "FILE",
+ help = "Writes to FILE or stdout if omitted"
+ )]
+ pub output: Option<String>,
+ #[clap(
+ short = 'B',
+ long,
+ help = "Emits binary data",
+ )]
+ pub binary: bool,
+ #[clap(
+ long = "time",
+ value_name = "TIME",
+ help = "Sets the certification time to TIME (as ISO 8601)",
+ long_help = "\
+Sets the certification time to TIME. TIME is interpreted as an ISO 8601
+timestamp. To set the certification time to June 9, 2011 at midnight UTC,
+you can do:
+
+$ sq certify --time 20130721 neal.pgp ada.pgp ada
+
+To include a time, add a T, the time and optionally the timezone (the
+default timezone is UTC):
+
+$ sq certify --time 20130721T0550+0200 neal.pgp ada.pgp ada
+",
+ )]
+ pub time: Option<String>,
+ #[clap(
+ short = 'd',
+ long = "depth",
+ value_name = "TRUST_DEPTH",
+ help = "Sets the trust depth",
+ long_help =
+ "Sets the trust depth (sometimes referred to as the trust level). \
+ 0 means a normal certification of <CERTIFICATE, USERID>. \
+ 1 means CERTIFICATE is also a trusted introducer, 2 means \
+ CERTIFICATE is a meta-trusted introducer, etc. The default is 0.",
+ )]
+ //TODO: use usize, not String
+ pub depth: Option<String>,
+ #[clap(
+ short = 'a',
+ long = "amount",
+ value_name = "TRUST_AMOUNT",
+ help = "Sets the amount of trust",
+ long_help =
+ "Sets the amount of trust. Values between 1 and 120 are meaningful. \
+ 120 means fully trusted. Values less than 120 indicate the degree \
+ of trust. 60 is usually used for partially \
+ trusted. The default is 120.",
+ )]
+ //TODO: use usize, not String
+ pub amount: Option<String>,
+ #[clap(
+ short = 'r',
+ long = "regex",
+ value_name = "REGEX",
+ help = "Adds a regular expression to constrain \
+ what a trusted introducer can certify",
+ long_help =
+ "Adds a regular expression to constrain \
+ what a trusted introducer can certify. \
+ The regular expression must match \
+ the certified User ID in all intermediate \
+ introducers, and the certified certificate. \
+ Multiple regular expressions may be \
+ specified. In that case, at least \
+ one must match.",
+ )]
+ pub regex: Vec<String>,
+ #[clap(
+ short = 'l',
+ long = "local",
+ help = "Makes the certification a local certification",
+ long_help =
+ "Makes the certification a local \
+ certification. Normally, local \
+ certifications are not exported.",
+ )]
+ pub local: bool,
+ #[clap(
+ long = "non-revocable",
+ help = "Marks the certification as being non-revocable",
+ long_help =
+ "Marks the certification as being non-revocable. \
+ That is, you cannot later revoke this \
+ certification. This should normally only \
+ be used with an expiration.",
+ )]
+ pub non_revocable: bool,
+ #[clap(
+ long,
+ value_names = &["NAME", "VALUE"],
+ number_of_values = 2,
+ help = "Adds a notation to the certification.",
+ long_help = "Adds a notation to the certification. \
+ A user-defined notation's name must be of the form \
+ \"name@a.domain.you.control.org\". If the notation's name starts \
+ with a !, then the notation is marked as being critical. If a \
+ consumer of a signature doesn't understand a critical notation, \
+ then it will ignore the signature. The notation is marked as \
+ being human readable."
+ )]
+ pub notation: Option<Vec<String>>,
+ #[clap(
+ long = "expires",
+ value_name = "TIME",
+ help = "Makes the certification expire at TIME (as ISO 8601)",
+ long_help =
+ "Makes the certification expire at TIME (as ISO 8601). \
+ Use \"never\" to create certifications that do not expire.",
+ )]
+ pub expires: Option<String>,
+ #[clap(
+ long = "expires-in",
+ value_name = "DURATION",
+ // Catch negative numbers.
+ allow_hyphen_values = true,
+ help = "Makes the certification expire after DURATION \
+ (as N[ymwds]) [default: 5y]",
+ long_help =
+ "Makes the certification expire after DURATION. \
+ Either \"N[ymwds]\", for N years, months, \
+ weeks, days, seconds, or \"never\". [default: 5y]",
+ )]
+ pub expires_in: Option<String>,
+ #[clap(
+ long = "private-key-store",
+ value_name = "KEY_STORE",
+ help = "Provides parameters for private key store",
+ )]
+ pub private_key_store: Option<String>,
+ #[clap(
+ value_name = "CERTIFIER-KEY",
+ required = true,
+ index = 1,
+ help = "Creates the certification using CERTIFIER-KEY.",
+ )]
+ pub certifier: String,
+ #[clap(
+ value_name = "CERTIFICATE",
+ required = true,
+ index = 2,
+ help = "Certifies CERTIFICATE.",
+ )]
+ pub certificate: String,
+ #[clap(
+ value_name = "USERID",
+ required = true,
+ index = 3,
+ help = "Certifies USERID for CERTIFICATE.",
+ )]
+ pub userid: String,
+}
+
+#[derive(Parser, Debug)]
+#[clap(
name = "wkd",
display_order = 420,
about = "Interacts with Web Key Directories",