1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-26 01:52:45 +02:00

Added a way to update preferences

This commit is contained in:
Werner Koch 2001-08-09 13:11:51 +00:00
parent aa9da2b07e
commit a255ea76ae
11 changed files with 325 additions and 22 deletions

3
NEWS
View File

@ -13,7 +13,8 @@
except for revocation certificates and --enarmor mode.
* The command "primary" in the edit menu can be used to change the
primary UID.
primary UID, "setpref" and "updpref" can be used to change the
preferences.
Noteworthy changes in version 1.0.6 (2001-05-29)
------------------------------------------------

2
TODO
View File

@ -1,6 +1,8 @@
* add listing of notation data
* Make sure that we only update the latest self-signatures.
* Check the changes to the gpg random agtherer on all W32 platforms.
* Check that a key signature can be revoked and later be signed again.

View File

@ -326,6 +326,12 @@ primary key is changed.</para></listitem></varlistentry>
<term>passwd</term>
<listitem><para>
Change the passphrase of the secret key.</para></listitem></varlistentry>
<varlistentry>
<term>primary</term>
<listitem><para>
Flag the current user id as the primary one, removes the primary user
id flag from all other user ids and sets the timestamp of all
affected self-signatures one second ahead.</para></listitem></varlistentry>
<varlistentry>
<term>uid &ParmN;</term>
<listitem><para>
@ -348,6 +354,21 @@ List preferences.</para></listitem></varlistentry>
<term>showpref</term>
<listitem><para>
More verbose preferences listing.</para></listitem></varlistentry>
<term>setpref &ParmString;</term>
<listitem><para>
Set the list of user ID preferences to &ParmString;, this should be
a string similar to the one printed by "pref". Using an empty string
will set the default preference string, using "none" will set the
preferences to nil. Only available algorithms are allowed. This
command just initializes an internal list and does not change anything
unless another command which changes the self-signatures is used.
</para></listitem></varlistentry>
<term>updpref</term>
<listitem><para>
Change the preferences of all user IDs (or just of the selected ones
to the current list of preferences. The timestamp of all affected
self-signatures fill be advanced by one second.
</para></listitem></varlistentry>
<varlistentry>
<term>toggle</term>
<listitem><para>
@ -1509,6 +1530,14 @@ Don't change the permissions of a secret keyring back to user
read/write only. Use this option only if you really know what you are doing.
</para></listitem></varlistentry>
<varlistentry>
<term>--preference-list &ParmString</term>
<listitem><para>
Set the list of preferences to &ParmString;, this list should be
a string similar to the one printed by the command "pref" in the edit
menu.
</para></listitem></varlistentry>
</variablelist>
</refsect1>

View File

@ -1,3 +1,17 @@
2001-08-09 Werner Koch <wk@gnupg.org>
* g10.c (main): New option "--preference-list"
* keyedit.c (keyedit_menu): New commands "setpref" and "updpref".
(menu_set_preferences): New.
* keygen.c (keygen_set_std_prefs): New.
(set_one_pref): New.
(check_zip_algo): New.
(keygen_get_std_prefs): New.
(keygen_upd_std_prefs): New
(keygen_add_std_prefs): Move the pref setting code into the above fnc.
* build-packet.c (build_sig_subpkt): Updated the list of allowed
to update subpackets.
2001-08-08 Werner Koch <wk@gnupg.org>
* packet.h (subpktarea_t): New.

View File

@ -744,6 +744,9 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
else if (find_subpkt (sig->hashed, type, NULL, NULL) ) {
switch (type) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
delete_sig_subpkt (sig->hashed, type);
break;
default:

View File

@ -208,6 +208,7 @@ enum cmd_and_opt_values { aNull = 0,
oNoSigCache,
oNoSigCreateCheck,
oPreservePermissions,
oPreferenceList,
oEmu3DESS2KBug, /* will be removed in 1.1 */
oEmuMDEncodeBug,
aTest };
@ -408,6 +409,7 @@ static ARGPARSE_OPTS opts[] = {
{ oNoExpensiveTrustChecks, "no-expensive-trust-checks", 0, "@" },
{ aDeleteSecretAndPublicKey, "delete-secret-and-public-key",256, "@" },
{ oPreservePermissions, "preserve-permissions", 0, "@"},
{ oPreferenceList, "preference-list", 2, "@"},
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
{ oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
{0} };
@ -619,6 +621,7 @@ main( int argc, char **argv )
char *def_digest_string = NULL;
char *s2k_cipher_string = NULL;
char *s2k_digest_string = NULL;
char *preference_list = NULL;
int pwfd = -1;
int with_fpr = 0; /* make an option out of --fingerprint */
#ifdef USE_SHM_COPROCESSING
@ -992,7 +995,7 @@ main( int argc, char **argv )
break;
case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break;
case oPreservePermissions: opt.preserve_permissions=1; break;
case oPreferenceList: preference_list = pargs.r.ret_str; break;
default : pargs.err = configfp? 1:2; break;
}
}
@ -1092,6 +1095,8 @@ main( int argc, char **argv )
log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
}
if (preference_list && keygen_set_std_prefs (preference_list))
log_error(_("invalid preferences\n"));
if( log_get_errorcount(0) )
g10_exit(2);

View File

@ -197,6 +197,12 @@ static struct helptexts { const char *key; const char *help; } helptexts[] = {
"a second one is available."
)},
{ "keyedit.updpref.okay", N_(
"Change the preferences of all user IDs (or just of the selected ones)\n"
"to the current list of preferences. The timestamp of all affected\n"
"self-signatures fill be advanced by one second.\n"
)},
{ "passphrase.enter", N_(
""

View File

@ -51,6 +51,7 @@ static int menu_delsig( KBNODE pub_keyblock );
static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_select_uid( KBNODE keyblock, int idx );
static int menu_select_key( KBNODE keyblock, int idx );
static int count_uids( KBNODE keyblock );
@ -575,7 +576,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
cmdLSIGN, cmdREVSIG, cmdREVKEY, cmdDELSIG, cmdPRIMARY,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF, cmdUPDPREF,
cmdINVCMD, cmdNOP };
static struct { const char *name;
enum cmdids id;
@ -612,6 +613,8 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
{ N_("t" ) , cmdTOGGLE , 1,0,0, NULL },
{ N_("pref") , cmdPREF , 0,1,0, N_("list preferences") },
{ N_("showpref"), cmdSHOWPREF , 0,1,0, N_("list preferences") },
{ N_("setpref") , cmdSETPREF , 1,1,0, N_("set preference list") },
{ N_("updpref") , cmdUPDPREF , 1,1,0, N_("updated preferences") },
{ N_("passwd") , cmdPASSWD , 1,1,0, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0,1,0, N_("change the ownertrust") },
{ N_("revsig") , cmdREVSIG , 0,1,0, N_("revoke signatures") },
@ -682,6 +685,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
cur_keyblock = keyblock;
for(;;) { /* main loop */
int i, arg_number;
const char *arg_string = "";
char *p;
tty_printf("\n");
@ -725,6 +729,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
trim_spaces(answer);
trim_spaces(p);
arg_number = atoi(p);
arg_string = p;
}
for(i=0; cmds[i].name; i++ ) {
@ -952,6 +957,31 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
show_key_with_all_names( keyblock, 0, 0, 0, 2 );
break;
case cmdSETPREF:
keygen_set_std_prefs ( !*arg_string? "default" : arg_string );
break;
case cmdUPDPREF:
{
char *p = keygen_get_std_prefs ();
tty_printf (("Current preference list: %s\n"), p);
m_free (p);
}
if (cpr_get_answer_is_yes ("keyedit.updpref.okay",
count_selected_uids (keyblock)?
_("Really update the preferences"
" for the selected user IDs? "):
_("Really update the preferences? "))){
if ( menu_set_preferences (keyblock, sec_keyblock) ) {
update_trust_record (keyblock, 0, NULL);
merge_keys_and_selfsig (keyblock);
modified = 1;
redisplay = 1;
}
}
break;
case cmdNOP:
break;
@ -1665,6 +1695,7 @@ change_primary_uid_cb ( PKT_signature *sig, void *opaque )
return 0;
}
/*
* Set the primary uid flag for the selected UID. We will also reset
* all other primary uid flags. For this to work with have to update
@ -1765,6 +1796,82 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock )
}
/*
* Set preferences to new values for the selected user IDs
*/
static int
menu_set_preferences (KBNODE pub_keyblock, KBNODE sec_keyblock )
{
PKT_secret_key *sk; /* copy of the main sk */
PKT_public_key *main_pk;
PKT_user_id *uid;
KBNODE node;
u32 keyid[2];
int selected, select_all;
int modified = 0;
select_all = !count_selected_uids (pub_keyblock);
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
/* Now we can actually change the self signature(s) */
main_pk = NULL;
uid = NULL;
selected = 0;
for ( node=pub_keyblock; node; node = node->next ) {
if ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break; /* ready */
if ( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
main_pk = node->pkt->pkt.public_key;
keyid_from_pk( main_pk, keyid );
}
else if ( node->pkt->pkttype == PKT_USER_ID ) {
uid = node->pkt->pkt.user_id;
selected = select_all || (node->flag & NODFLG_SELUID);
}
else if ( main_pk && uid && selected
&& node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
if ( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
&& (uid && (sig->sig_class&~3) == 0x10)
&& sig->version >= 4 ) {
/* This is a selfsignature which is to be replaced
* We have to ignore v3 signatures because they are
* not able to carry the preferences */
PKT_signature *newsig;
PACKET *newpkt;
int rc;
rc = update_keysig_packet (&newsig, sig,
main_pk, uid,
sk,
keygen_upd_std_prefs,
NULL );
if( rc ) {
log_error ("update_keysig_packet failed: %s\n",
g10_errstr(rc));
free_secret_key( sk );
return 0;
}
/* replace the packet */
newpkt = m_alloc_clear( sizeof *newpkt );
newpkt->pkttype = PKT_SIGNATURE;
newpkt->pkt.signature = newsig;
free_packet( node->pkt );
m_free( node->pkt );
node->pkt = newpkt;
modified = 1;
}
}
}
free_secret_key( sk );
return modified;
}
/****************
* Select one user id or remove all selection if index is 0.
* Returns: True if the selection changed;

View File

@ -35,6 +35,9 @@
#include "status.h"
#include "i18n.h"
#define MAX_PREFS 30
enum para_name {
pKEYTYPE,
pKEYLENGTH,
@ -83,6 +86,15 @@ struct output_control_s {
};
static int prefs_initialized = 0;
static byte sym_prefs[MAX_PREFS];
static int nsym_prefs;
static byte hash_prefs[MAX_PREFS];
static int nhash_prefs;
static byte zip_prefs[MAX_PREFS];
static int nzip_prefs;
static void do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl );
static int write_keyblock( IOBUF out, KBNODE node );
@ -124,6 +136,140 @@ keygen_add_key_expire( PKT_signature *sig, void *opaque )
}
static int
set_one_pref (ulong val, int type, int (*cf)(int), byte *buf, int *nbuf)
{
int i;
if (!val || val > 127 || cf (val)) {
log_info (_("preference %c%lu is not valid\n"), type, val);
return -1;
}
for (i=0; i < *nbuf; i++ ) {
if (buf[i] == val) {
log_info (_("preference %c%lu duplicated\n"), type, val);
return -1;
}
}
if (*nbuf >= MAX_PREFS) {
log_info (_("too many `%c' preferences\n"), type);
return -1;
}
buf[(*nbuf)++] = val;
return 0;
}
static int
check_zip_algo (int algo)
{
return algo < 0 || algo > 2;
}
/*
* Parse the supplied string and use it to set the standard preferences.
* The String is expected to be in a forma like the one printed by "prefs",
* something like: "S10 S3 H3 H2 Z2 Z1". Use NULL to set the default
* preferences.
* Returns: 0 = okay
*/
int
keygen_set_std_prefs (const char *string)
{
byte sym[MAX_PREFS], hash[MAX_PREFS], zip[MAX_PREFS];
int nsym=0, nhash=0, nzip=0;
ulong val;
const char *s, *s2;
int rc = 0;
if (!string || !ascii_strcasecmp (string, "default"))
string = "S7 S10 S3 S4 H3 H2 Z2 Z1";
else if (!ascii_strcasecmp (string, "none"))
string = "";
for (s=string; *s; s = s2) {
if ((*s=='s' || *s == 'S') && isdigit(s[1]) ) {
val = strtoul (++s, (char**)&s2, 10);
if (set_one_pref (val, 'S', check_cipher_algo, sym, &nsym))
rc = -1;
}
else if ((*s=='h' || *s == 'H') && isdigit(s[1]) ) {
val = strtoul (++s, (char**)&s2, 10);
if (set_one_pref (val, 'H', check_digest_algo, hash, &nhash))
rc = -1;
}
else if ((*s=='z' || *s == 'Z') && isdigit(s[1]) ) {
val = strtoul (++s, (char**)&s2, 10);
if (set_one_pref (val, 'Z', check_zip_algo, zip, &nzip))
rc = -1;
}
else if (isspace (*s))
s2 = s+1;
else {
log_info (_("invalid character in string\n"));
return -1;
}
}
if (!rc) {
memcpy (sym_prefs, sym, (nsym_prefs=nsym));
memcpy (hash_prefs, hash, (nhash_prefs=nhash));
memcpy (zip_prefs, zip, (nzip_prefs=nzip));
prefs_initialized = 1;
}
return rc;
}
/*
* Return a printable list of preferences. Caller must free.
*/
char *
keygen_get_std_prefs ()
{
char *buf;
int i;
if (!prefs_initialized)
keygen_set_std_prefs (NULL);
buf = m_alloc ( MAX_PREFS*3*5 + 1);
*buf = 0;
for (i=0; i < nsym_prefs; i++ )
sprintf (buf+strlen(buf), "S%d ", sym_prefs[i]);
for (i=0; i < nhash_prefs; i++ )
sprintf (buf+strlen(buf), "H%d ", hash_prefs[i]);
for (i=0; i < nzip_prefs; i++ )
sprintf (buf+strlen(buf), "Z%d ", zip_prefs[i]);
if (*buf) /* trim the trailing space */
buf[strlen(buf)-1] = 0;
return buf;
}
int
keygen_upd_std_prefs( PKT_signature *sig, void *opaque )
{
if (!prefs_initialized)
keygen_set_std_prefs (NULL);
if (nsym_prefs)
build_sig_subpkt (sig, SIGSUBPKT_PREF_SYM, sym_prefs, nsym_prefs);
else
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_SYM);
if (nhash_prefs)
build_sig_subpkt (sig, SIGSUBPKT_PREF_HASH, hash_prefs, nhash_prefs);
else
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_HASH);
if (nzip_prefs)
build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs);
else
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR);
return 0;
}
/****************
* Add preference to the self signature packet.
* This is only called for packets with version > 3.
@ -132,22 +278,9 @@ int
keygen_add_std_prefs( PKT_signature *sig, void *opaque )
{
byte buf[8];
keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_RIJNDAEL;
buf[1] = CIPHER_ALGO_TWOFISH;
buf[2] = CIPHER_ALGO_CAST5;
buf[3] = CIPHER_ALGO_BLOWFISH;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 4 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 2 );
buf[0] = 2;
buf[1] = 1;
build_sig_subpkt( sig, SIGSUBPKT_PREF_COMPR, buf, 2 );
keygen_upd_std_prefs (sig, opaque);
buf[0] = 0x80; /* no modify - It is reasonable that a key holder
* has the possibility to reject signatures from users

View File

@ -98,8 +98,11 @@ void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds,
/*-- keygen.c --*/
u32 ask_expiredate(void);
void generate_keypair( const char *fname );
int keygen_set_std_prefs (const char *string);
char *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
/*-- openfile.c --*/

View File

@ -925,7 +925,7 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
/****************
* Create a new signature packet based on an existing one.
* Only user ID signatureare supportted for now.
* Only user ID signaturs are supported for now.
* TODO: Merge this with make_keysig_packet.
*/
int
@ -967,9 +967,9 @@ update_keysig_packet( PKT_signature **ret_sig,
if ( sig->version >= 4 && mksubpkt)
rc = (*mksubpkt)(sig, opaque);
/* we increasethe timestamp by one second so that a future import
of this key will replace the existing one. We make sure that
we don't produce a timestamp in the future */
/* we increase the timestamp by one second so that a future import
of this key will replace the existing one. We also make sure that
we don't create a timestamp in the future */
sig->timestamp++;
while (sig->timestamp >= make_timestamp())
sleep (1);