diff options
author | Nora Widdecke <nora@sequoia-pgp.org> | 2022-06-03 11:59:34 +0200 |
---|---|---|
committer | Nora Widdecke <nora@sequoia-pgp.org> | 2022-06-08 14:49:43 +0200 |
commit | e87a3b5d869ad1ec22cb18a5792877121214971f (patch) | |
tree | c244652c4a7de7ca4a292a870680b1aefeac7882 | |
parent | 73bd7bf210e28b7385213adf9634d55e3ad31619 (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.rs | 343 |
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", |