mirror of
git://git.gnupg.org/gnupg.git
synced 2025-05-14 08:13:25 +02:00
gpg: New command --quick-tsign-key.
* g10/gpg.c (aQuickTSignKey): New. (opts): Add new command. (main): Parse args for it. * g10/keyedit.c: Include mbox-util.h. (parse_trustsig_string): New. (sign_uids): Add arg trustsig for use in quick mode. (keyedit_quick_sign): Also add arg trustsig and print a diagnostic on error.
This commit is contained in:
parent
6d49e86bba
commit
d90b290f97
8
NEWS
8
NEWS
@ -4,10 +4,12 @@ Noteworthy changes in version 2.5.6 (unreleased)
|
||||
* gpg: Add a flag to the filter expressions for left anchored
|
||||
substring match. [rGc12b7d047e]
|
||||
|
||||
* gpg: Fix double free of internal data. [T7547]
|
||||
|
||||
* gpg: New list option "show-trustsig" to avoid resorting to colon
|
||||
mode for this info.
|
||||
mode for this info. [rG41d6ae8f41]
|
||||
|
||||
* gpg: New command --quick-tsign-key to create a trust signature.
|
||||
|
||||
* gpg: Fix double free of internal data. [T7547]
|
||||
|
||||
* gpgsm: Extend --learn-card by an optional s/n argument. [T7379]
|
||||
|
||||
|
13
doc/gpg.texi
13
doc/gpg.texi
@ -1137,8 +1137,10 @@ from @option{--edit-key}.
|
||||
|
||||
@item --quick-sign-key @var{fpr} [@var{names}]
|
||||
@itemx --quick-lsign-key @var{fpr} [@var{names}]
|
||||
@itemx --quick-tsign-key @var{fpr} @var{trustspec} [@var{names}]
|
||||
@opindex quick-sign-key
|
||||
@opindex quick-lsign-key
|
||||
@opindex quick-tsign-key
|
||||
Directly sign a key from the passphrase without any further user
|
||||
interaction. The @var{fpr} must be the verified primary fingerprint
|
||||
of a key in the local keyring. If no @var{names} are given, all
|
||||
@ -1153,6 +1155,17 @@ non-exportable. If such a non-exportable signature already exists the
|
||||
you need to update an existing signature, for example to add or change
|
||||
notation data, you need to use the option @option{--force-sign-key}.
|
||||
|
||||
The command @option{--quick-tsign-key} creates a trust signature using
|
||||
the information from the @var{trustspec} string. The @var{trustspec}
|
||||
uses the format [T=]@var{dept},@var{value}[,@var{domain}]. @var{depth}
|
||||
is the length of the trust chain in the range 0 (identical to a
|
||||
standard key signature) to 255 (ridiculous long trust chain); the most
|
||||
common lengths for trust signatures are 1 and 2. @var{value} is
|
||||
either "f" or "full" which are mapped to a value of 120 or "m" or
|
||||
"marginal" which are mapped to a value of 60. The allowed range is 0
|
||||
to 255 but it is highly suggested to use only 60 or 120. @var{domain}
|
||||
is optional and a plain domain name like "example.org".
|
||||
|
||||
This command uses reasonable defaults and thus does not provide the
|
||||
full flexibility of the "sign" subcommand from @option{--edit-key}.
|
||||
Its intended use is to help unattended key signing by utilizing a list
|
||||
|
24
g10/gpg.c
24
g10/gpg.c
@ -130,6 +130,7 @@ enum cmd_and_opt_values
|
||||
aLSignKey,
|
||||
aQuickSignKey,
|
||||
aQuickLSignKey,
|
||||
aQuickTSignKey,
|
||||
aQuickRevSig,
|
||||
aQuickAddUid,
|
||||
aQuickAddKey,
|
||||
@ -529,6 +530,8 @@ static gpgrt_opt_t opts[] = {
|
||||
N_("quickly sign a key")),
|
||||
ARGPARSE_c (aQuickLSignKey, "quick-lsign-key",
|
||||
N_("quickly sign a key locally")),
|
||||
ARGPARSE_c (aQuickTSignKey, "quick-tsign-key",
|
||||
N_("quickly sign a key with a trust signature")),
|
||||
ARGPARSE_c (aQuickRevSig, "quick-revoke-sig" ,
|
||||
N_("quickly revoke a key signature")),
|
||||
ARGPARSE_c (aSignKey, "sign-key" ,N_("sign a key")),
|
||||
@ -2734,6 +2737,7 @@ main (int argc, char **argv)
|
||||
case aSign:
|
||||
case aQuickSignKey:
|
||||
case aQuickLSignKey:
|
||||
case aQuickTSignKey:
|
||||
case aQuickRevSig:
|
||||
case aSignKey:
|
||||
case aLSignKey:
|
||||
@ -4715,7 +4719,25 @@ main (int argc, char **argv)
|
||||
sl = NULL;
|
||||
for( ; argc; argc--, argv++)
|
||||
append_to_strlist2 (&sl, *argv, utf8_strings);
|
||||
keyedit_quick_sign (ctrl, fpr, sl, locusr, (cmd == aQuickLSignKey));
|
||||
keyedit_quick_sign (ctrl, fpr, sl, locusr,
|
||||
NULL, (cmd == aQuickLSignKey));
|
||||
free_strlist (sl);
|
||||
}
|
||||
break;
|
||||
|
||||
case aQuickTSignKey:
|
||||
{
|
||||
const char *fpr, *tsig;
|
||||
|
||||
if (argc < 2)
|
||||
wrong_args ("--quick-tsign-key fingerprint"
|
||||
" depth,[m|f][,domain] [userids]");
|
||||
fpr = *argv++; argc--;
|
||||
tsig = *argv++; argc--;
|
||||
sl = NULL;
|
||||
for( ; argc; argc--, argv++)
|
||||
append_to_strlist2 (&sl, *argv, utf8_strings);
|
||||
keyedit_quick_sign (ctrl, fpr, sl, locusr, tsig, 0);
|
||||
free_strlist (sl);
|
||||
}
|
||||
break;
|
||||
|
153
g10/keyedit.c
153
g10/keyedit.c
@ -44,6 +44,7 @@
|
||||
#include "../common/ttyio.h"
|
||||
#include "../common/status.h"
|
||||
#include "../common/i18n.h"
|
||||
#include "../common/mbox-util.h"
|
||||
#include "keyserver-internal.h"
|
||||
#include "call-agent.h"
|
||||
#include "../common/host2net.h"
|
||||
@ -380,6 +381,92 @@ sign_mk_attrib (PKT_signature * sig, void *opaque)
|
||||
}
|
||||
|
||||
|
||||
/* Parse a trust signature specification string into the 3 return
|
||||
* args. Returns 0 on success or an errorcode. Format for the string
|
||||
* is
|
||||
* ['T=']<depth>,<value>[,<domain>]
|
||||
* The optional prefix is just to allow c+p from the --check-sigs
|
||||
* output. The domain is optional, <depth> must be a value in the
|
||||
* range 0 to 255, value may either be value in the same range or -
|
||||
* preferred - 'm' or 'f'.
|
||||
*/
|
||||
static gpg_error_t
|
||||
parse_trustsig_string (const char *string,
|
||||
byte *trust_value, byte *trust_depth, char **regexp)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
char **fields;
|
||||
int nfields;
|
||||
int along;
|
||||
char *endp;
|
||||
|
||||
*trust_value = 0;
|
||||
*trust_depth = 0;
|
||||
*regexp = NULL;
|
||||
|
||||
if (!string)
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
if (*string == 'T' && string[1] == '=')
|
||||
string += 2;
|
||||
|
||||
fields = strtokenize (string, ",");
|
||||
if (!fields)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
for (nfields=0; fields[nfields]; nfields++)
|
||||
;
|
||||
if (nfields < 2 || nfields > 3)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
along = strtol (fields[0], &endp, 10);
|
||||
if (along < 0 || along > 255 || fields[0] == endp || *endp)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ERANGE);
|
||||
goto leave;
|
||||
}
|
||||
*trust_depth = along;
|
||||
if (!strcmp (fields[1], "m")|| !strcmp (fields[1], "marginal"))
|
||||
along = 60;
|
||||
else if (!strcmp (fields[1], "f")|| !strcmp (fields[1], "full"))
|
||||
along = 120;
|
||||
else
|
||||
{
|
||||
along = strtol (fields[1], &endp, 10);
|
||||
if (along < 0 || along > 255 || fields[1] == endp || *endp)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ERANGE);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
*trust_value = along;
|
||||
|
||||
if (nfields == 3)
|
||||
{
|
||||
if (!is_valid_domain_name (fields[2]))
|
||||
err = gpg_error (GPG_ERR_NO_NAME);
|
||||
else
|
||||
{
|
||||
*regexp = strconcat ("<[^>]+[@.]", fields[2], ">$", NULL);
|
||||
if (!*regexp)
|
||||
err = gpg_error_from_syserror ();
|
||||
}
|
||||
}
|
||||
|
||||
leave:
|
||||
xfree (fields);
|
||||
if (err && *regexp)
|
||||
{
|
||||
xfree (*regexp);
|
||||
*regexp = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Interactive version of parse_trustsig_string. */
|
||||
static void
|
||||
trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
|
||||
{
|
||||
@ -485,12 +572,13 @@ trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
|
||||
* is marked, all user ids will be signed; if some user_ids are marked
|
||||
* only those will be signed. FLAGS are the SIGN_UIDS_* constants.
|
||||
* For example with SIGN_UIDS_QUICK the function won't ask the user
|
||||
* and use sensible defaults.
|
||||
* and use sensible defaults. TRUSTSIGSTR is only used if also
|
||||
* SIGN_UIDS_TRUSTSIG is set.
|
||||
*/
|
||||
static int
|
||||
sign_uids (ctrl_t ctrl, estream_t fp,
|
||||
kbnode_t keyblock, strlist_t locusr, unsigned int flags,
|
||||
int *ret_modified)
|
||||
const char *trustsigstr, int *ret_modified)
|
||||
{
|
||||
int rc = 0;
|
||||
SK_LIST sk_list = NULL;
|
||||
@ -498,9 +586,11 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||
PKT_public_key *pk = NULL;
|
||||
KBNODE node, uidnode;
|
||||
PKT_public_key *primary_pk = NULL;
|
||||
char *trust_regexp = NULL;
|
||||
int select_all = (!count_selected_uids (keyblock)
|
||||
|| (flags & SIGN_UIDS_INTERACTIVE));
|
||||
|
||||
|
||||
/* Build a list of all signators.
|
||||
*
|
||||
* We use the CERT flag to request the primary which must always
|
||||
@ -516,7 +606,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
|
||||
{
|
||||
u32 sk_keyid[2], pk_keyid[2];
|
||||
char *p, *trust_regexp = NULL;
|
||||
char *p;
|
||||
int class = 0, selfsig = 0;
|
||||
u32 duration = 0, timestamp = 0;
|
||||
byte trust_depth = 0, trust_value = 0;
|
||||
@ -917,9 +1007,21 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & SIGN_UIDS_TRUSTSIG) && !(flags & SIGN_UIDS_QUICK))
|
||||
trustsig_prompt (&trust_value, &trust_depth, &trust_regexp);
|
||||
}
|
||||
if ((flags & SIGN_UIDS_TRUSTSIG))
|
||||
{
|
||||
xfree (trust_regexp);
|
||||
trust_regexp = NULL;
|
||||
if ((flags & SIGN_UIDS_QUICK))
|
||||
{
|
||||
rc = parse_trustsig_string (trustsigstr, &trust_value,
|
||||
&trust_depth, &trust_regexp);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
trustsig_prompt (&trust_value, &trust_depth, &trust_regexp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & SIGN_UIDS_QUICK))
|
||||
{
|
||||
@ -1065,6 +1167,8 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||
} /* End loop over signators. */
|
||||
|
||||
leave:
|
||||
xfree (trust_regexp);
|
||||
trust_regexp = NULL;
|
||||
release_sk_list (sk_list);
|
||||
return rc;
|
||||
}
|
||||
@ -1730,7 +1834,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||
break;
|
||||
}
|
||||
|
||||
sign_uids (ctrl, NULL, keyblock, locusr, myflags, &modified);
|
||||
sign_uids (ctrl, NULL, keyblock, locusr, myflags, NULL, &modified);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2910,10 +3014,12 @@ find_by_primary_fpr (ctrl_t ctrl, const char *fpr,
|
||||
key are signed using the default signing key. If UIDS is an empty
|
||||
list all usable UIDs are signed, if it is not empty, only those
|
||||
user ids matching one of the entries of the list are signed. With
|
||||
LOCAL being true the signatures are marked as non-exportable. */
|
||||
LOCAL being true the signatures are marked as non-exportable. If
|
||||
TRUSTSIG is given a trust signature is created; see
|
||||
parse_trustsig_string(). */
|
||||
void
|
||||
keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||
strlist_t locusr, int local)
|
||||
strlist_t locusr, const char *trustsig, int local)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
kbnode_t keyblock = NULL;
|
||||
@ -2929,6 +3035,20 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||
check_trustdb_stale (ctrl);
|
||||
#endif
|
||||
|
||||
/* Do an early check on an arg for an immediate error message. */
|
||||
if (trustsig)
|
||||
{
|
||||
byte trust_depth, trust_value;
|
||||
char *trust_regexp;
|
||||
err = parse_trustsig_string (trustsig, &trust_value,
|
||||
&trust_depth, &trust_regexp);
|
||||
xfree (trust_regexp);
|
||||
(void)trust_depth;
|
||||
(void)trust_value;
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* We require a fingerprint because only this uniquely identifies a
|
||||
key and may thus be used to select a key for unattended key
|
||||
signing. */
|
||||
@ -3036,10 +3156,14 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||
}
|
||||
|
||||
/* Sign. */
|
||||
sign_uids (ctrl, es_stdout, keyblock, locusr,
|
||||
(SIGN_UIDS_QUICK | (local? SIGN_UIDS_LOCAL : 0)),
|
||||
&modified);
|
||||
err = sign_uids (ctrl, es_stdout, keyblock, locusr,
|
||||
(SIGN_UIDS_QUICK
|
||||
| (local? SIGN_UIDS_LOCAL : 0)
|
||||
| (trustsig? SIGN_UIDS_TRUSTSIG : 0)),
|
||||
trustsig, &modified);
|
||||
es_fflush (es_stdout);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
if (modified)
|
||||
{
|
||||
@ -3058,7 +3182,10 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||
|
||||
leave:
|
||||
if (err)
|
||||
write_status_error ("keyedit.sign-key", err);
|
||||
{
|
||||
log_error (_("creating key signature failed: %s\n"), gpg_strerror (err));
|
||||
write_status_error ("keyedit.sign-key", err);
|
||||
}
|
||||
release_kbnode (keyblock);
|
||||
keydb_release (kdbhd);
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ void keyedit_quick_addadsk (ctrl_t ctrl, const char *fpr, const char *adskfpr);
|
||||
void keyedit_quick_revuid (ctrl_t ctrl, const char *username,
|
||||
const char *uidtorev);
|
||||
void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
|
||||
strlist_t uids, strlist_t locusr, int local);
|
||||
strlist_t uids, strlist_t locusr,
|
||||
const char *trustsig, int local);
|
||||
void keyedit_quick_revsig (ctrl_t ctrl, const char *username,
|
||||
const char *sigtorev, strlist_t affected_uids);
|
||||
void keyedit_quick_set_expire (ctrl_t ctrl,
|
||||
|
Loading…
x
Reference in New Issue
Block a user