mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +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
5 changed files with 183 additions and 18 deletions
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
|
* gpg: Add a flag to the filter expressions for left anchored
|
||||||
substring match. [rGc12b7d047e]
|
substring match. [rGc12b7d047e]
|
||||||
|
|
||||||
* gpg: Fix double free of internal data. [T7547]
|
|
||||||
|
|
||||||
* gpg: New list option "show-trustsig" to avoid resorting to colon
|
* 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]
|
* 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}]
|
@item --quick-sign-key @var{fpr} [@var{names}]
|
||||||
@itemx --quick-lsign-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-sign-key
|
||||||
@opindex quick-lsign-key
|
@opindex quick-lsign-key
|
||||||
|
@opindex quick-tsign-key
|
||||||
Directly sign a key from the passphrase without any further user
|
Directly sign a key from the passphrase without any further user
|
||||||
interaction. The @var{fpr} must be the verified primary fingerprint
|
interaction. The @var{fpr} must be the verified primary fingerprint
|
||||||
of a key in the local keyring. If no @var{names} are given, all
|
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
|
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}.
|
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
|
This command uses reasonable defaults and thus does not provide the
|
||||||
full flexibility of the "sign" subcommand from @option{--edit-key}.
|
full flexibility of the "sign" subcommand from @option{--edit-key}.
|
||||||
Its intended use is to help unattended key signing by utilizing a list
|
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,
|
aLSignKey,
|
||||||
aQuickSignKey,
|
aQuickSignKey,
|
||||||
aQuickLSignKey,
|
aQuickLSignKey,
|
||||||
|
aQuickTSignKey,
|
||||||
aQuickRevSig,
|
aQuickRevSig,
|
||||||
aQuickAddUid,
|
aQuickAddUid,
|
||||||
aQuickAddKey,
|
aQuickAddKey,
|
||||||
|
@ -529,6 +530,8 @@ static gpgrt_opt_t opts[] = {
|
||||||
N_("quickly sign a key")),
|
N_("quickly sign a key")),
|
||||||
ARGPARSE_c (aQuickLSignKey, "quick-lsign-key",
|
ARGPARSE_c (aQuickLSignKey, "quick-lsign-key",
|
||||||
N_("quickly sign a key locally")),
|
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" ,
|
ARGPARSE_c (aQuickRevSig, "quick-revoke-sig" ,
|
||||||
N_("quickly revoke a key signature")),
|
N_("quickly revoke a key signature")),
|
||||||
ARGPARSE_c (aSignKey, "sign-key" ,N_("sign a key")),
|
ARGPARSE_c (aSignKey, "sign-key" ,N_("sign a key")),
|
||||||
|
@ -2734,6 +2737,7 @@ main (int argc, char **argv)
|
||||||
case aSign:
|
case aSign:
|
||||||
case aQuickSignKey:
|
case aQuickSignKey:
|
||||||
case aQuickLSignKey:
|
case aQuickLSignKey:
|
||||||
|
case aQuickTSignKey:
|
||||||
case aQuickRevSig:
|
case aQuickRevSig:
|
||||||
case aSignKey:
|
case aSignKey:
|
||||||
case aLSignKey:
|
case aLSignKey:
|
||||||
|
@ -4715,7 +4719,25 @@ main (int argc, char **argv)
|
||||||
sl = NULL;
|
sl = NULL;
|
||||||
for( ; argc; argc--, argv++)
|
for( ; argc; argc--, argv++)
|
||||||
append_to_strlist2 (&sl, *argv, utf8_strings);
|
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);
|
free_strlist (sl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
147
g10/keyedit.c
147
g10/keyedit.c
|
@ -44,6 +44,7 @@
|
||||||
#include "../common/ttyio.h"
|
#include "../common/ttyio.h"
|
||||||
#include "../common/status.h"
|
#include "../common/status.h"
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "../common/mbox-util.h"
|
||||||
#include "keyserver-internal.h"
|
#include "keyserver-internal.h"
|
||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
#include "../common/host2net.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
|
static void
|
||||||
trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
|
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
|
* 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.
|
* only those will be signed. FLAGS are the SIGN_UIDS_* constants.
|
||||||
* For example with SIGN_UIDS_QUICK the function won't ask the user
|
* 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
|
static int
|
||||||
sign_uids (ctrl_t ctrl, estream_t fp,
|
sign_uids (ctrl_t ctrl, estream_t fp,
|
||||||
kbnode_t keyblock, strlist_t locusr, unsigned int flags,
|
kbnode_t keyblock, strlist_t locusr, unsigned int flags,
|
||||||
int *ret_modified)
|
const char *trustsigstr, int *ret_modified)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
SK_LIST sk_list = NULL;
|
SK_LIST sk_list = NULL;
|
||||||
|
@ -498,9 +586,11 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||||
PKT_public_key *pk = NULL;
|
PKT_public_key *pk = NULL;
|
||||||
KBNODE node, uidnode;
|
KBNODE node, uidnode;
|
||||||
PKT_public_key *primary_pk = NULL;
|
PKT_public_key *primary_pk = NULL;
|
||||||
|
char *trust_regexp = NULL;
|
||||||
int select_all = (!count_selected_uids (keyblock)
|
int select_all = (!count_selected_uids (keyblock)
|
||||||
|| (flags & SIGN_UIDS_INTERACTIVE));
|
|| (flags & SIGN_UIDS_INTERACTIVE));
|
||||||
|
|
||||||
|
|
||||||
/* Build a list of all signators.
|
/* Build a list of all signators.
|
||||||
*
|
*
|
||||||
* We use the CERT flag to request the primary which must always
|
* 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)
|
for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next)
|
||||||
{
|
{
|
||||||
u32 sk_keyid[2], pk_keyid[2];
|
u32 sk_keyid[2], pk_keyid[2];
|
||||||
char *p, *trust_regexp = NULL;
|
char *p;
|
||||||
int class = 0, selfsig = 0;
|
int class = 0, selfsig = 0;
|
||||||
u32 duration = 0, timestamp = 0;
|
u32 duration = 0, timestamp = 0;
|
||||||
byte trust_depth = 0, trust_value = 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))
|
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);
|
trustsig_prompt (&trust_value, &trust_depth, &trust_regexp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(flags & SIGN_UIDS_QUICK))
|
if (!(flags & SIGN_UIDS_QUICK))
|
||||||
{
|
{
|
||||||
|
@ -1065,6 +1167,8 @@ sign_uids (ctrl_t ctrl, estream_t fp,
|
||||||
} /* End loop over signators. */
|
} /* End loop over signators. */
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
xfree (trust_regexp);
|
||||||
|
trust_regexp = NULL;
|
||||||
release_sk_list (sk_list);
|
release_sk_list (sk_list);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1730,7 +1834,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sign_uids (ctrl, NULL, keyblock, locusr, myflags, &modified);
|
sign_uids (ctrl, NULL, keyblock, locusr, myflags, NULL, &modified);
|
||||||
}
|
}
|
||||||
break;
|
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
|
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
|
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
|
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
|
void
|
||||||
keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
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;
|
gpg_error_t err = 0;
|
||||||
kbnode_t keyblock = NULL;
|
kbnode_t keyblock = NULL;
|
||||||
|
@ -2929,6 +3035,20 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||||
check_trustdb_stale (ctrl);
|
check_trustdb_stale (ctrl);
|
||||||
#endif
|
#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
|
/* We require a fingerprint because only this uniquely identifies a
|
||||||
key and may thus be used to select a key for unattended key
|
key and may thus be used to select a key for unattended key
|
||||||
signing. */
|
signing. */
|
||||||
|
@ -3036,10 +3156,14 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sign. */
|
/* Sign. */
|
||||||
sign_uids (ctrl, es_stdout, keyblock, locusr,
|
err = sign_uids (ctrl, es_stdout, keyblock, locusr,
|
||||||
(SIGN_UIDS_QUICK | (local? SIGN_UIDS_LOCAL : 0)),
|
(SIGN_UIDS_QUICK
|
||||||
&modified);
|
| (local? SIGN_UIDS_LOCAL : 0)
|
||||||
|
| (trustsig? SIGN_UIDS_TRUSTSIG : 0)),
|
||||||
|
trustsig, &modified);
|
||||||
es_fflush (es_stdout);
|
es_fflush (es_stdout);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
if (modified)
|
if (modified)
|
||||||
{
|
{
|
||||||
|
@ -3058,7 +3182,10 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
if (err)
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("creating key signature failed: %s\n"), gpg_strerror (err));
|
||||||
write_status_error ("keyedit.sign-key", err);
|
write_status_error ("keyedit.sign-key", err);
|
||||||
|
}
|
||||||
release_kbnode (keyblock);
|
release_kbnode (keyblock);
|
||||||
keydb_release (kdbhd);
|
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,
|
void keyedit_quick_revuid (ctrl_t ctrl, const char *username,
|
||||||
const char *uidtorev);
|
const char *uidtorev);
|
||||||
void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
|
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,
|
void keyedit_quick_revsig (ctrl_t ctrl, const char *username,
|
||||||
const char *sigtorev, strlist_t affected_uids);
|
const char *sigtorev, strlist_t affected_uids);
|
||||||
void keyedit_quick_set_expire (ctrl_t ctrl,
|
void keyedit_quick_set_expire (ctrl_t ctrl,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue