1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

See ChangeLog: Mon Sep 18 16:35:45 CEST 2000 Werner Koch

This commit is contained in:
Werner Koch 2000-09-18 14:35:34 +00:00
parent c2fff8f204
commit 986d928ce2
46 changed files with 1780 additions and 852 deletions

View file

@ -1,3 +1,81 @@
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
* parse-packet.c (dump_sig_subpkt): Dump key flags.
(parse_one_sig_subpkt,can_handle_critical): Add KeyFlags support.
* build-packet.c (build_sig_subpkt): Ditto.
* g10.c: New option --allow-freeform-uid. By Jeroen C. van Gelderen.
* keygen.c (ask_user_id): Implemented here.
* parse-packet.c (dump_sig_subpkt): Print info about the ARR.
* openfile.c (overwrite_filep): Always return okay if the file is
called /dev/null.
(make_outfile_name): Add ".sign" to the list of know extensions.
(open_sigfile): Ditto.
* getkey.c: Large parts rewritten to have a better sub key selection
and handle some meta information from signatures more correctly.
(get_primary_seckey): Removed.
* seckey_cert.c (do_check): Set main keyid from the data in the sk.
* free-packet.c (copy_public_parts_to_secret_key): New.
* sig-check.c (check_key_signature2): Enabled shortcut for already
checked signatures.
* keydb.h: New macros IS_xxx_SIG, IS_xxx_REV.
* misc.c (openpgp_pk_algo_usage): New.
* packet.h: New field req_uage and do not use pubkey_usage anymore
to request a specific usage. Changed at all places.
* keyid.c (keyid_from_sk): Cache the keyid in the sk
* passphrase.c (hash_passphrase): Removed funny assert. Reported by
David Mathog.
* keyedit.c (keyedit_menu): Allow "debug" on secret keys.
* keygen.c (keygen_add_std_prefs): Changed order of preferences to
twofish, cast5, blowfish.
* gpg.c: The --trusted-key option is back.
* trustdb.c (verify_own_key): Handle this option.
(add_ultimate_key): Moved stuff from verify_own_key to this new func.
(register_trusted_key): New.
* openfile.c (try_make_homedir): Changes for non-Posix systems.
* gpg.c (main): Take the default homedir from macro.
* encode.c (encode_simple, encode_crypt): Fix for large files.
* sign.c (sign_file): Ditto.
* gpg.c (main): Don't set --quite along with --no-tty. By Frank Tobin.
* misc.c (disable_core_dump): Don't display a warning here but a return
a status value and ...
* gpg.c (main): ...print warning here. Suggested by Sam Roberts.
* misc.c (print_pubkey_algo_note): Do not print the RSA notice.
* sig-check.c (do_signature_check): Do not emit the RSA status message.
* pubkey-enc.c (get_session_key): Ditto.
* ringedit.c (cmp_seckey): Fix for v4 RSA keys.
* seckey-cert.c (do_check): Workaround for PGP 7 bug.
* pkclist.c (algo_available): Removed hack to disable Twofish.
* gpg.c (main): Default S2K algorithms are now SHA1 and CAST5 - this
should solve a lot of compatibility problems with other OpenPGP
apps because those algorithms are SHOULD and not optional. The old
way to force it was by using the --openpgp option whith the drawback
that this would disable a couple of workarounds for PGP.
* gpg.c: New option --merge-only. Suggested by Brendan O'Dea.
* import.c (import_one): Implemented it here.
(import_secret_one): Ditto.
(print_stats): and give some stats.
* gpg.c: New option --try-all-secrets on suggestion from
Matthias Urlichs.
* pubkey-enc.c (get_session_key): Quite easy to implement here.
Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de>
* gpg.c: New option --use-agent

View file

@ -701,6 +701,7 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_NOTATION:
case SIGSUBPKT_POLICY:
case SIGSUBPKT_REVOC_REASON:
case SIGSUBPKT_KEY_FLAGS:
hashed = 1; break;
default: hashed = 0; break;
}

View file

@ -220,6 +220,10 @@ encode_simple( const char *filename, int mode )
if( filename && !opt.textmode && !mode ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
/* we can't yet encode the length of very large files,
* so we switch to partial length encoding in this case */
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
filesize = 0;
}
else
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
@ -368,6 +372,10 @@ encode_crypt( const char *filename, STRLIST remusr )
if( filename && !opt.textmode ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
/* we can't yet encode the length of very large files,
* so we switch to partial lengthn encoding in this case */
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
filesize = 0;
}
else
filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */

View file

@ -139,6 +139,32 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
return copy_public_key_new_namehash( d, s, NULL );
}
/****************
* Replace all common parts of a sk by the one from the public key.
* This is a hack and a better solution will be to just store the real secret
* parts somewhere and don't duplicate all the other stuff.
*/
void
copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
{
sk->expiredate = pk->expiredate;
sk->pubkey_algo = pk->pubkey_algo;
sk->pubkey_usage= pk->pubkey_usage;
sk->created = pk->created;
sk->req_usage = pk->req_usage;
sk->req_algo = pk->req_algo;
sk->has_expired = pk->has_expired;
sk->is_revoked = pk->is_revoked;
sk->is_valid = pk->is_valid;
sk->main_keyid[0]= pk->main_keyid[0];
sk->main_keyid[1]= pk->main_keyid[1];
sk->keyid[0] = pk->keyid[0];
sk->keyid[1] = pk->keyid[1];
}
PKT_signature *
copy_signature( PKT_signature *d, PKT_signature *s )
{
@ -450,3 +476,7 @@ cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
}

File diff suppressed because it is too large Load diff

View file

@ -179,6 +179,7 @@ enum cmd_and_opt_values { aNull = 0,
oDisableCipherAlgo,
oDisablePubkeyAlgo,
oAllowNonSelfsignedUID,
oAllowFreeformUID,
oNoLiteral,
oSetFilesize,
oHonorHttpProxy,
@ -188,7 +189,9 @@ enum cmd_and_opt_values { aNull = 0,
oNoRandomSeedFile,
oNoAutoKeyRetrieve,
oUseAgent,
oEmu3DESS2KBug, /* will be removed in 1.1 */
oMergeOnly,
oTryAllSecrets,
oTrustedKey,
oEmuMDEncodeBug,
aTest };
@ -290,6 +293,7 @@ static ARGPARSE_OPTS opts[] = {
{ oCompletesNeeded, "completes-needed", 1, "@"},
{ oMarginalsNeeded, "marginals-needed", 1, "@"},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oTrustedKey, "trusted-key", 2, N_("|KEYID|ulimately trust this key")},
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
{ oOpenPGP, "openpgp", 0, N_("set all packet, cipher and digest options to OpenPGP behavior")},
@ -362,6 +366,7 @@ static ARGPARSE_OPTS opts[] = {
{ oDisableCipherAlgo, "disable-cipher-algo", 2, "@" },
{ oDisablePubkeyAlgo, "disable-pubkey-algo", 2, "@" },
{ oAllowNonSelfsignedUID, "allow-non-selfsigned-uid", 0, "@" },
{ oAllowFreeformUID, "allow-freeform-uid", 0, "@" },
{ oNoLiteral, "no-literal", 0, "@" },
{ oSetFilesize, "set-filesize", 20, "@" },
{ oHonorHttpProxy,"honor-http-proxy", 0, "@" },
@ -370,7 +375,8 @@ static ARGPARSE_OPTS opts[] = {
{ oIgnoreTimeConflict, "ignore-time-conflict", 0, "@" },
{ oNoRandomSeedFile, "no-random-seed-file", 0, "@" },
{ oNoAutoKeyRetrieve, "no-auto-key-retrieve", 0, "@" },
{ oEmu3DESS2KBug, "emulate-3des-s2k-bug", 0, "@"},
{ oMergeOnly, "merge-only", 0, "@" },
{ oTryAllSecrets, "try-all-secrets", 0, "@" },
{ oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
{0} };
@ -601,6 +607,7 @@ main( int argc, char **argv )
char **orig_argv;
const char *fname;
char *username;
int may_coredump;
STRLIST sl, remusr= NULL, locusr=NULL;
STRLIST nrings=NULL, sec_nrings=NULL;
armor_filter_context_t afx;
@ -642,7 +649,7 @@ main( int argc, char **argv )
}
gcry_control( GCRYCTL_USE_SECURE_RNDPOOL );
disable_core_dumps();
may_coredump = disable_core_dumps();
init_signals();
create_dotlock(NULL); /* register locking cleanup */
i18n_init();
@ -653,8 +660,8 @@ main( int argc, char **argv )
opt.def_digest_algo = 0;
opt.def_compress_algo = 2;
opt.s2k_mode = 3; /* iterated+salted */
opt.s2k_digest_algo = GCRY_MD_RMD160;
opt.s2k_cipher_algo = GCRY_CIPHER_BLOWFISH;
opt.s2k_digest_algo = GCRY_MD_SHA1;
opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
@ -666,11 +673,7 @@ main( int argc, char **argv )
opt.homedir = getenv("GNUPGHOME");
#endif
if( !opt.homedir || !*opt.homedir ) {
#ifdef HAVE_DRIVE_LETTERS
opt.homedir = "c:/gnupg-test";
#else
opt.homedir = "~/.gnupg-test";
#endif
opt.homedir = GNUPG_HOMEDIR;
}
/* check whether we have a config file on the commandline */
@ -801,7 +804,7 @@ main( int argc, char **argv )
case oArmor: opt.armor = 1; opt.no_armor=0; break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
case oQuiet: opt.quiet = 1; break;
case oNoTTY: opt.quiet = 1; tty_no_terminal(1); break;
case oNoTTY: tty_no_terminal(1); break;
case oDryRun: opt.dry_run = 1; break;
case oInteractive: opt.interactive = 1; break;
case oVerbose:
@ -894,7 +897,6 @@ main( int argc, char **argv )
opt.s2k_digest_algo = GCRY_MD_SHA1;
opt.s2k_cipher_algo = GCRY_CIPHER_CAST5;
break;
case oEmu3DESS2KBug: opt.emulate_bugs |= EMUBUG_3DESS2K; break;
case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
@ -965,6 +967,7 @@ main( int argc, char **argv )
}
break;
case oAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid = 1; break;
case oAllowFreeformUID: opt.allow_freeform_uid = 1; break;
case oNoLiteral: opt.no_literal = 1; break;
case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break;
case oHonorHttpProxy: opt.honor_http_proxy = 1; break;
@ -973,6 +976,9 @@ main( int argc, char **argv )
case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break;
case oNoRandomSeedFile: use_random_seed = 0; break;
case oNoAutoKeyRetrieve: opt.auto_key_retrieve = 0; break;
case oMergeOnly: opt.merge_only = 1; break;
case oTryAllSecrets: opt.try_all_secrets = 1; break;
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
default : pargs.err = configfp? 1:2; break;
}
@ -1001,6 +1007,10 @@ main( int argc, char **argv )
log_info("used in a production environment or with production keys!\n");
}
#endif
if( may_coredump && !opt.quiet )
log_info(_("WARNING: program may create a core file!\n"));
if (opt.no_literal) {
log_info(_("NOTE: %s is not for normal use!\n"), "--no-literal");
if (opt.textmode)
@ -1406,9 +1416,13 @@ main( int argc, char **argv )
case aPrimegen:
{ int mode = argc < 2 ? 0 : atoi(*argv);
{
#if 1
log_error( "command is currently not implemented\n");
#else
/* FIXME: disabled until we have an API to create primes */
int mode = argc < 2 ? 0 : atoi(*argv);
#if 0 /* FIXME: disabled until we have an API to create primes */
if( mode == 1 && argc == 2 ) {
mpi_print( stdout, generate_public_prime( atoi(argv[1]) ), 1);
}
@ -1435,9 +1449,9 @@ main( int argc, char **argv )
mpi_release(g);
}
else
#endif
wrong_args("--gen-prime mode bits [qbits] ");
putchar('\n');
#endif
}
break;

View file

@ -50,6 +50,7 @@ static struct {
ulong secret_read;
ulong secret_imported;
ulong secret_dups;
ulong skipped_new_keys;
} stats;
@ -201,6 +202,9 @@ print_stats()
{
if( !opt.quiet ) {
log_info(_("Total number processed: %lu\n"), stats.count );
if( stats.skipped_new_keys )
log_info(_(" skipped new keys: %lu\n"),
stats.skipped_new_keys );
if( stats.no_user_id )
log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id );
if( stats.imported || stats.imported_rsa ) {
@ -413,6 +417,13 @@ import_one( const char *fname, KBNODE keyblock, int fast )
log_error( _("key %08lX: public key not found: %s\n"),
(ulong)keyid[1], gpg_errstr(rc));
}
else if ( rc && opt.merge_only ) {
if( opt.verbose )
log_info( _("key %08lX: new key - skipped\n"), (ulong)keyid[1] );
rc = 0;
fast = 1; /* so that we don't get into the trustdb update */
stats.skipped_new_keys++;
}
else if( rc ) { /* insert this key */
/* get default resource */
if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
@ -583,7 +594,7 @@ import_secret_one( const char *fname, KBNODE keyblock )
/* do we have this key already in one of our secrings ? */
rc = seckey_available( keyid );
if( rc == GPGERR_NO_SECKEY ) { /* simply insert this key */
if( rc == GPGERR_NO_SECKEY && !opt.merge_only ) { /* simply insert this key */
/* get default resource */
if( get_keyblock_handle( NULL, 1, &kbpos ) ) {
log_error("no default secret keyring\n");

View file

@ -31,6 +31,15 @@
#define MAX_FINGERPRINT_LEN 20
#define IS_KEY_SIG(s) ((s)->sig_class == 0x1f)
#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
#define IS_SUBKEY_SIG(s) ((s)->sig_class == 0x18)
#define IS_KEY_REV(s) ((s)->sig_class == 0x20)
#define IS_UID_REV(s) ((s)->sig_class == 0x30)
#define IS_SUBKEY_REV(s) ((s)->sig_class == 0x28)
struct getkey_ctx_s;
typedef struct getkey_ctx_s *GETKEY_CTX;

View file

@ -592,7 +592,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
{ N_("sign") , cmdSIGN , 0,1,1, N_("sign the key") },
{ N_("s") , cmdSIGN , 0,1,1, NULL },
{ N_("lsign") , cmdLSIGN , 0,1,1, N_("sign the key locally") },
{ N_("debug") , cmdDEBUG , 0,1,0, NULL },
{ N_("debug") , cmdDEBUG , 0,0,0, NULL },
{ N_("adduid") , cmdADDUID , 1,1,0, N_("add a user ID") },
{ N_("deluid") , cmdDELUID , 0,1,0, N_("delete user ID") },
{ N_("addkey") , cmdADDKEY , 1,1,0, N_("add a secondary key") },

View file

@ -136,8 +136,8 @@ keygen_add_std_prefs( PKT_signature *sig, void *opaque )
keygen_add_key_expire( sig, opaque );
buf[0] = GCRY_CIPHER_TWOFISH;
buf[1] = GCRY_CIPHER_BLOWFISH;
buf[2] = GCRY_CIPHER_CAST5;
buf[1] = GCRY_CIPHER_CAST5;
buf[2] = GCRY_CIPHER_BLOWFISH;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 3 );
buf[0] = GCRY_MD_RMD160;
@ -889,7 +889,11 @@ ask_user_id( int mode )
aname = cpr_get("keygen.name",_("Real name: "));
trim_spaces(aname);
cpr_kill_prompt();
if( strpbrk( aname, "<([])>" ) )
if( opt.allow_freeform_uid )
break;
if( strpbrk( aname, "<>" ) )
tty_printf(_("Invalid character in name\n"));
else if( isdigit(*aname) )
tty_printf(_("Name may not start with a digit\n"));

View file

@ -166,11 +166,17 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
if( !keyid )
keyid = dummy_keyid;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
if( sk->keyid[0] || sk->keyid[1] ) {
keyid[0] = sk->keyid[0];
keyid[1] = sk->keyid[1];
}
else if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
if( pubkey_get_npkey(sk->pubkey_algo) )
v3_keyid( sk->skey[0], keyid ); /* take n */
else
keyid[0] = keyid[1] = 0;
sk->keyid[0] = keyid[0];
sk->keyid[1] = keyid[1];
}
else {
const byte *dp;
@ -180,6 +186,8 @@ keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
gcry_md_close(md);
sk->keyid[0] = keyid[0];
sk->keyid[1] = keyid[1];
}
return keyid[1];

View file

@ -51,7 +51,7 @@ char *make_radix64_string( const byte *data, size_t len );
/*-- misc.c --*/
void trap_unaligned(void);
void disable_core_dumps(void);
int disable_core_dumps(void);
u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a );
@ -65,6 +65,7 @@ int mpi_print( FILE *fp, MPI a, int mode );
int openpgp_cipher_test_algo( int algo );
int openpgp_pk_test_algo( int algo, unsigned int usage_flags );
int openpgp_pk_algo_usage ( int algo );
int openpgp_md_test_algo( int algo );
int pubkey_get_npkey( int algo );

View file

@ -68,22 +68,24 @@ trap_unaligned(void)
#endif
void
int
disable_core_dumps()
{
#ifndef HAVE_DOSISH_SYSTEM
#ifdef HAVE_DOSISH_SYSTEM
return 0;
#else
#ifdef HAVE_SETRLIMIT
struct rlimit limit;
limit.rlim_cur = 0;
limit.rlim_max = 0;
if( !setrlimit( RLIMIT_CORE, &limit ) )
return;
if( errno != EINVAL )
return 0;
if( errno != EINVAL && errno != ENOSYS )
log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
#endif
if( !opt.quiet )
log_info(_("WARNING: program may create a core file!\n"));
return 1;
#endif
}
@ -318,15 +320,6 @@ print_pubkey_algo_note( int algo )
{
if( algo >= 100 && algo <= 110 )
no_exp_algo();
else if( is_RSA( algo ) ) {
static int did_note = 0;
if( !did_note ) {
did_note = 1;
log_info(_("RSA keys are deprecated; please consider "
"creating a new key and use this key in the future\n"));
}
}
}
void
@ -362,7 +355,7 @@ print_digest_algo_note( int algo )
/****************
* Wrapper around the libgcrypt function with addional checks on
* openPGP contrainst for the algo ID.
* openPGP contraints for the algo ID.
*/
int
openpgp_cipher_test_algo( int algo )
@ -382,6 +375,40 @@ openpgp_pk_test_algo( int algo, unsigned int usage_flags )
return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
}
int
openpgp_pk_algo_usage ( int algo )
{
int usage = 0;
/* some are hardwired */
switch ( algo ) {
case GCRY_PK_RSA:
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
break;
case GCRY_PK_RSA_E:
usage = GCRY_PK_USAGE_ENCR;
break;
case GCRY_PK_RSA_S:
usage = GCRY_PK_USAGE_SIGN;
break;
case GCRY_PK_ELG_E:
usage = GCRY_PK_USAGE_ENCR;
break;
case GCRY_PK_DSA:
usage = GCRY_PK_USAGE_SIGN;
break;
case GCRY_PK_ELG:
usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
break;
default:
usage = gcry_pk_algo_info ( algo, GCRYCTL_GET_ALGO_USAGE,
NULL, NULL);
}
return usage;
}
int
openpgp_md_test_algo( int algo )

View file

@ -70,6 +70,11 @@ overwrite_filep( const char *fname )
if( access( fname, F_OK ) )
return 1; /* does not exist */
#ifndef HAVE_DOSISH_SYSTEM
if ( !strcmp ( fname, "/dev/null" ) )
return 1; /* does not do any harm */
#endif
/* fixme: add some backup stuff in case of overwrite */
if( opt.answer_yes )
return 1;
@ -105,6 +110,12 @@ make_outfile_name( const char *iname )
buf[n-4] = 0;
return buf;
}
else if( n > 5 && !CMP_FILENAME(iname+n-5,".sign") ) {
char *buf = gcry_xstrdup( iname );
buf[n-5] = 0;
return buf;
}
log_info(_("%s: unknown suffix\n"), iname );
return NULL;
@ -241,6 +252,7 @@ open_sigfile( const char *iname )
if( iname && !(*iname == '-' && !iname[1]) ) {
len = strlen(iname);
if( len > 4 && ( !strcmp(iname + len - 4, ".sig")
|| ( len > 5 && !strcmp(iname + len - 5, ".sign") )
|| !strcmp(iname + len - 4, ".asc")) ) {
char *buf;
buf = gcry_xstrdup(iname);
@ -305,10 +317,24 @@ copy_options_file( const char *destdir )
void
try_make_homedir( const char *fname )
{
const char *defhome = GNUPG_HOMEDIR;
/* Create the directory only if the supplied directory name
* is the same as the default one. This way we avoid to create
* arbitrary directories when a non-default homedirectory is used.
* To cope with HOME, we do compare only the suffix if we see that
* the default homedir does start with a tilde.
*/
if( opt.dry_run )
return;
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
if ( ( *defhome == '~'
&& ( strlen(fname) >= strlen (defhome+1)
&& !strcmp(fname+strlen(defhome+1)-strlen(defhome+1),
defhome+1 ) ))
|| ( *defhome != '~'
&& !compare_filenames( fname, defhome ) )
) {
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
@ -321,3 +347,5 @@ try_make_homedir( const char *fname )
}
}

View file

@ -84,6 +84,7 @@ struct {
const char *set_policy_url;
int use_embedded_filename;
int allow_non_selfsigned_uid;
int allow_freeform_uid;
int no_literal;
ulong set_filesize;
int honor_http_proxy;
@ -92,6 +93,8 @@ struct {
int command_fd;
int auto_key_retrieve;
int use_agent;
int merge_only;
int try_all_secrets;
} opt;

View file

@ -128,8 +128,15 @@ typedef struct {
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte pubkey_usage; /* for now only used to pass it to getkey() */
byte pubkey_usage; /* the actual allowed usage as set by getkey() */
u32 created; /* according to the self-signature */
byte req_usage; /* hack to pass a request to getkey() */
byte req_algo; /* Ditto */
u32 has_expired; /* set to the expiration date if expired */
int is_revoked; /* key has been revoked */
int is_valid; /* key (especially subkey) is valid */
ulong local_id; /* internal use, valid if > 0 */
u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2]; /* calculated by keyid_from_pk() */
byte *namehash; /* if != NULL: found by this name */
MPI pkey[GNUPG_MAX_NPKEY];
@ -142,6 +149,14 @@ typedef struct {
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte pubkey_usage;
u32 created; /* according to the self-signature */
byte req_usage;
byte req_algo;
u32 has_expired; /* set to the expiration date if expired */
int is_revoked; /* key has been revoked */
int is_valid; /* key (especially subkey) is valid */
u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2];
byte is_primary;
byte is_protected; /* The secret info is protected and must */
/* be decrypted before use, the protected */
@ -169,6 +184,10 @@ typedef struct {
int len; /* length of the name */
char *photo; /* if this is not NULL, the packet is a photo ID */
int photolen; /* and the length of the photo */
int help_key_usage;
u32 help_key_expire;
int is_primary;
u32 created; /* according to the self-signature */
char name[1];
} PKT_user_id;
@ -322,6 +341,8 @@ PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d,
PKT_public_key *s,
const byte *namehash );
void copy_public_parts_to_secret_key( PKT_public_key *pk,
PKT_secret_key *sk );
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );

View file

@ -700,6 +700,17 @@ dump_sig_subpkt( int hashed, int type, int critical,
const char *p=NULL;
int i;
/* The CERT has warning out with explains how to use GNUPG to
* detect the ARRs - we print our old message here when it is a faked
* ARR and add an additional notice */
if ( type == SIGSUBPKT_ARR && !hashed ) {
printf("\tsubpkt %d len %u (additional recipient request)\n"
"WARNING: PGP versions > 5.0 and < 6.5.8 will automagically "
"encrypt to this key and thereby reveal the plaintext to "
"the owner of this ARR key. Detailed info follows:\n",
type, (unsigned)length );
}
printf("\t%s%ssubpkt %d len %u (", /*)*/
critical ? "critical ":"",
hashed ? "hashed ":"", type, (unsigned)length );
@ -737,9 +748,6 @@ dump_sig_subpkt( int hashed, int type, int critical,
printf("key expires after %s",
strtimevalue( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_ARR:
p = "additional recipient request";
break;
case SIGSUBPKT_PREF_SYM:
fputs("pref-sym-algos:", stdout );
for( i=0; i < length; i++ )
@ -809,8 +817,10 @@ dump_sig_subpkt( int hashed, int type, int critical,
print_string( stdout, buffer, length, ')' );
break;
case SIGSUBPKT_KEY_FLAGS:
p = "key flags";
break;
fputs ( "key flags:", stdout );
for( i=0; i < length; i++ )
printf(" %02X", buffer[i] );
break;
case SIGSUBPKT_SIGNERS_UID:
p = "signer's user ID";
break;
@ -821,6 +831,16 @@ dump_sig_subpkt( int hashed, int type, int critical,
p = ")";
}
break;
case SIGSUBPKT_ARR:
fputs("Big Brother's key (ignored): ", stdout );
if( length < 22 )
p = "[too short]";
else {
printf("c=%02x a=%d f=", buffer[0], buffer[1] );
for( i=2; i < length; i++ )
printf("%02X", buffer[i] );
}
break;
case SIGSUBPKT_PRIV_ADD_SIG:
p = "signs additional user ID";
break;
@ -846,6 +866,8 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
if( n < 4 )
break;
return 0;
case SIGSUBPKT_KEY_FLAGS:
return 0;
case SIGSUBPKT_EXPORTABLE:
if( !n )
break;
@ -867,6 +889,10 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_POLICY:
return 0;
case SIGSUBPKT_PRIMARY_UID:
if ( n != 1 )
break;
return 0;
case SIGSUBPKT_PRIV_ADD_SIG:
/* because we use private data, we check the GNUPG marker */
if( n < 24 )
@ -897,6 +923,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_KEY_FLAGS:
return 1;
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */
@ -1288,7 +1315,8 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
sk->version = version;
sk->is_primary = pkttype == PKT_SECRET_KEY;
sk->pubkey_algo = algorithm;
sk->pubkey_usage = 0; /* not yet used */
sk->req_usage = 0;
sk->pubkey_usage = 0; /* will be set by getkey functions */
}
else {
PKT_public_key *pk = pkt->pkt.public_key;
@ -1298,7 +1326,9 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
pk->hdrbytes = hdrlen;
pk->version = version;
pk->pubkey_algo = algorithm;
pk->pubkey_usage = 0; /* not yet used */
pk->req_usage = 0;
pk->pubkey_usage = 0; /* will be set bey getkey functions */
pk->is_revoked = 0;
pk->keyid[0] = 0;
pk->keyid[1] = 0;
}

View file

@ -640,7 +640,6 @@ hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
else {
gcry_md_write( md, s2k->salt, 8 );
count -= 8;
assert( count >= 0 );
gcry_md_write( md, pw, count );
}
}

View file

@ -814,13 +814,12 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
any_recipients = 1;
else if( (use & GCRY_PK_USAGE_ENCR) && !opt.no_encrypt_to ) {
pk = gcry_xcalloc( 1, sizeof *pk );
pk->pubkey_usage = use;
pk->req_usage = use;
if( (rc = get_pubkey_byname( NULL, pk, rov->d, NULL )) ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), rov->d, gpg_errstr(rc) );
}
else if( !(rc=openpgp_pk_test_algo(pk->pubkey_algo, use )) ) {
/* Skip the actual key if the key is already present
* in the list */
if (key_present_in_pk_list(pk_list, pk) == 0) {
@ -871,7 +870,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
if( pk )
free_public_key( pk );
pk = gcry_xcalloc( 1, sizeof *pk );
pk->pubkey_usage = use;
pk->req_usage = use;
rc = get_pubkey_byname( NULL, pk, answer, NULL );
if( rc )
tty_printf(_("No such user ID.\n"));
@ -937,7 +936,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
}
else if( !any_recipients && (def_rec = default_recipient()) ) {
pk = gcry_xcalloc( 1, sizeof *pk );
pk->pubkey_usage = use;
pk->req_usage = use;
rc = get_pubkey_byname( NULL, pk, def_rec, NULL );
if( rc )
log_error(_("unknown default recipient `%s'\n"), def_rec );
@ -962,7 +961,7 @@ build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use )
continue; /* encrypt-to keys are already handled */
pk = gcry_xcalloc( 1, sizeof *pk );
pk->pubkey_usage = use;
pk->req_usage = use;
if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), remusr->d, gpg_errstr(rc) );
@ -1033,8 +1032,6 @@ static int
algo_available( int preftype, int algo )
{
if( preftype == PREFTYPE_SYM ) {
if( algo == GCRY_CIPHER_TWOFISH )
return 0; /* we don't want to generate Twofish messages for now*/
return algo && !openpgp_cipher_test_algo( algo );
}
else if( preftype == PREFTYPE_HASH ) {

View file

@ -106,14 +106,11 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
PKT_secret_key *sk = NULL;
int rc;
if( is_RSA(k->pubkey_algo) ) /* warn about that */
write_status(STATUS_RSA_OR_IDEA);
rc = openpgp_pk_test_algo( k->pubkey_algo, 0 );
if( rc )
goto leave;
if( k->keyid[0] || k->keyid[1] ) {
if( (k->keyid[0] || k->keyid[1]) && !opt.try_all_secrets ) {
sk = gcry_xcalloc( 1, sizeof *sk );
sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
if( !(rc = get_seckey( sk, k->keyid )) )

View file

@ -1114,7 +1114,13 @@ cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
n = pubkey_get_nskey( req_sk->pubkey_algo );
for(i=0; i < n; i++ ) {
if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
/* Note: because v4 protected keys have nothing in the
* mpis except for the first one, we skip all NULL MPIs.
* This might not be always correct in cases where the both
* keys do not match in their secret parts but we can ignore that
* because the need for this function is quite ugly. */
if( req_sk->skey[1] && sk->skey[i]
&& mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
return -1;
}
return 0;

View file

@ -100,10 +100,8 @@ do_check( PKT_secret_key *sk )
keyid_from_sk( sk, keyid );
keyid[2] = keyid[3] = 0;
if( !sk->is_primary ) {
PKT_secret_key *sk2 = gcry_xcalloc( 1, sizeof *sk2 );
if( !get_primary_seckey( sk2, keyid ) )
keyid_from_sk( sk2, keyid+2 );
free_secret_key( sk2 );
keyid[2] = sk->main_keyid[0];
keyid[3] = sk->main_keyid[1];
}
dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
&sk->protect.s2k, 0 );
@ -128,11 +126,14 @@ do_check( PKT_secret_key *sk )
size_t ndata;
unsigned int ndatabits;
byte *p, *data;
u16 csumc = 0;
i = pubkey_get_npkey(sk->pubkey_algo);
assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
p = gcry_mpi_get_opaque( sk->skey[i], &ndatabits );
ndata = (ndatabits+7)/8;
if ( ndata > 1 )
csumc = p[ndata-2] << 8 | p[ndata-1];
data = gcry_xmalloc_secure( ndata );
gcry_cipher_decrypt( cipher_hd, data, ndata, p, ndata );
mpi_release( sk->skey[i] ); sk->skey[i] = NULL ;
@ -145,6 +146,10 @@ do_check( PKT_secret_key *sk )
else {
csum = checksum( data, ndata-2);
sk->csum = data[ndata-2] << 8 | data[ndata-1];
if ( sk->csum != csum ) {
/* This is a PGP 7.0.0 workaround */
sk->csum = csumc; /* take the encrypted one */
}
}
/* must check it here otherwise the mpi_read_xx would fail
* because the length may have an arbitrary value */
@ -321,8 +326,6 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
#warning FIXME: replace set/get buffer
if( sk->version >= 4 ) {
/* FIXME: There is a bug in this function for all algorithms
* where the secret MPIs are more than 1 */
byte *bufarr[GNUPG_MAX_NSKEY];
unsigned narr[GNUPG_MAX_NSKEY];
unsigned nbits[GNUPG_MAX_NSKEY];

View file

@ -134,9 +134,6 @@ do_signature_check( PKT_signature *sig, GCRY_MD_HD digest,
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
int rc=0;
if( is_RSA(sig->pubkey_algo) )
write_status(STATUS_RSA_OR_IDEA);
*r_expiredate = 0;
if( get_pubkey( pk, sig->keyid ) )
rc = GPGERR_NO_PUBKEY;
@ -451,10 +448,18 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
sig = node->pkt->pkt.signature;
algo = sig->digest_algo;
#if 0 /* I am not sure whether this is a good thing to do */
if( sig->flags.checked )
#if 0
if( sig->flags.checked ) {
log_debug("check_key_signature: already checked: %s\n",
sig->flags.valid? "good":"bad" );
if ( sig->flags.valid )
return 0; /* shortcut already checked signatures */
/* FIXME: We should also do this with bad signatures but here we
* have to distinguish between several reasons; e.g. for a missing
* public key. the key may now be available.
* For now we simply don't shortcut bad signatures
*/
}
#endif
if( (rc=openpgp_md_test_algo(algo)) )

View file

@ -485,6 +485,10 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
if( fname ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("WARNING: `%s' is an empty file\n"), fname );
/* we can't yet encode the length of very large files,
* so we switch to partial length encoding in this case */
if ( filesize >= IOBUF_FILELENGTH_LIMIT )
filesize = 0;
/* because the text_filter modifies the length of the
* data, it is not possible to know the used length

View file

@ -59,7 +59,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
PKT_secret_key *sk;
sk = gcry_xcalloc( 1, sizeof *sk );
sk->pubkey_usage = use;
sk->req_usage = use;
if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
free_secret_key( sk ); sk = NULL;
log_error("no default secret key: %s\n", gpg_errstr(rc) );
@ -90,7 +90,7 @@ build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
PKT_secret_key *sk;
sk = gcry_xcalloc( 1, sizeof *sk );
sk->pubkey_usage = use;
sk->req_usage = use;
if( (rc = get_seckey_byname( sk, locusr->d, unlock )) ) {
free_secret_key( sk ); sk = NULL;
log_error(_("skipped `%s': %s\n"), locusr->d, gpg_errstr(rc) );

View file

@ -109,6 +109,7 @@ static TN used_tns;
static int alloced_tns;
static int max_alloced_tns;
static struct keyid_list *trusted_key_list;
static LOCAL_ID_TABLE new_lid_table(void);
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
@ -463,6 +464,64 @@ lid_from_keyid_no_sdir( u32 *keyid )
************* Initialization ****************
***********************************************/
void
register_trusted_key( const char *string )
{
u32 keyid[2];
struct keyid_list *r;
if( classify_user_id( string, keyid, NULL, NULL, NULL ) != 11 ) {
log_error(_("'%s' is not a valid long keyID\n"), string );
return;
}
for( r = trusted_key_list; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] )
return;
r = gcry_xmalloc( sizeof *r );
r->keyid[0] = keyid[0];
r->keyid[1] = keyid[1];
r->next = trusted_key_list;
trusted_key_list = r;
}
static void
add_ultimate_key( PKT_public_key *pk, u32 *keyid )
{
int rc;
/* first make sure that the pubkey is in the trustdb */
rc = query_trust_record( pk );
if( rc == -1 && opt.dry_run )
return;
if( rc == -1 ) { /* put it into the trustdb */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
log_error(_("key %08lX: can't put it into the trustdb\n"),
(ulong)keyid[1] );
return;
}
}
else if( rc ) {
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
return;
}
if( DBG_TRUST )
log_debug("key %08lX.%lu: stored into ultikey_table\n",
(ulong)keyid[1], pk->local_id );
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
log_error(_("key %08lX: already in trusted key table\n"),
(ulong)keyid[1]);
else if( opt.verbose > 1 )
log_info(_("key %08lX: accepted as trusted key.\n"),
(ulong)keyid[1]);
}
/****************
* Verify that all our public keys are in the trustdb.
*/
@ -474,7 +533,27 @@ verify_own_keys(void)
PKT_secret_key *sk = gcry_xcalloc( 1, sizeof *sk );
PKT_public_key *pk = gcry_xcalloc( 1, sizeof *pk );
u32 keyid[2];
struct keyid_list *kl;
/* put the trusted keys into the ultikey table */
for( kl = trusted_key_list; kl; kl = kl->next ) {
keyid[0] = kl->keyid[0];
keyid[1] = kl->keyid[1];
/* get the public key */
memset( pk, 0, sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_info(_("key %08lX: no public key for trusted key - skipped\n"),
(ulong)keyid[1] );
}
else {
add_ultimate_key( pk, keyid );
release_public_key_parts( pk );
}
}
/* And now add all secret keys to the ultikey table */
while( !(rc=enum_secret_keys( &enum_context, sk, 0 ) ) ) {
int have_pk = 0;
@ -487,6 +566,10 @@ verify_own_keys(void)
log_info(_("NOTE: secret key %08lX is NOT protected.\n"),
(ulong)keyid[1] );
for( kl = trusted_key_list; kl; kl = kl->next ) {
if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
goto skip; /* already in trusted key table */
}
/* see whether we can access the public key of this secret key */
memset( pk, 0, sizeof *pk );
@ -504,33 +587,8 @@ verify_own_keys(void)
goto skip;
}
/* make sure that the pubkey is in the trustdb */
rc = query_trust_record( pk );
if( rc == -1 && opt.dry_run )
goto skip;
if( rc == -1 ) { /* put it into the trustdb */
rc = insert_trust_record_by_pk( pk );
if( rc ) {
log_error(_("key %08lX: can't put it into the trustdb\n"),
(ulong)keyid[1] );
goto skip;
}
}
else if( rc ) {
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
goto skip;
add_ultimate_key( pk, keyid );
}
if( DBG_TRUST )
log_debug("key %08lX.%lu: stored into ultikey_table\n",
(ulong)keyid[1], pk->local_id );
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
log_error(_("key %08lX: already in trusted key table\n"),
(ulong)keyid[1]);
else if( opt.verbose > 1 )
log_info(_("key %08lX: accepted as trusted key.\n"),
(ulong)keyid[1]);
skip:
release_secret_key_parts( sk );
if( have_pk )
@ -541,6 +599,15 @@ verify_own_keys(void)
else
rc = 0;
/* release the trusted keyid table */
{ struct keyid_list *kl2;
for( kl = trusted_key_list; kl; kl = kl2 ) {
kl2 = kl->next;
gcry_free( kl );
}
trusted_key_list = NULL;
}
enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
free_secret_key( sk );
free_public_key( pk );
@ -548,6 +615,8 @@ verify_own_keys(void)
}
/****************
* Perform some checks over the trustdb
* level 0: only open the db