diff --git a/AUTHORS b/AUTHORS index d641aa7f0..866f57190 100644 --- a/AUTHORS +++ b/AUTHORS @@ -28,3 +28,6 @@ fr.po TRANSLATIONS Walter Koch ?????????? de.po +TRANSLATIONS Gregory Steuck ?????????? +ru.po + diff --git a/ChangeLog b/ChangeLog index 1a25ff32e..067375367 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Sun Oct 25 19:49:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (g10defs.h): New macro GNUPG_DATADIR. + Wed Oct 21 17:24:24 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in: Removed gettext kludge diff --git a/Makefile.am b/Makefile.am index c81de2692..567fccdd3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,9 +13,11 @@ g10defs.h : config.h echo "#ifdef __MINGW32__"; \ echo "#define G10_LOCALEDIR \"c:/lib/gnupg/locale\""; \ echo "#define GNUPG_LIBDIR \"c:/lib/gnupg\""; \ + echo "#define GNUPG_DATADIR \"c:/lib/gnupg\""; \ echo "#else";\ echo "#define G10_LOCALEDIR \"$(prefix)/$(DATADIRNAME)/locale\""; \ echo "#define GNUPG_LIBDIR \"$(libdir)/gnupg\""; \ + echo "#define GNUPG_DATADIR \"$(datadir)/gnupg\""; \ echo "#endif";\ ) >g10defs.h @@ -36,13 +38,24 @@ dist-hook: # maintainer only cvs-get: - rsync -avuzb --exclude '*~' koch@ftp.guug.de:work/gnupg . + rsync -Cavuzb --exclude scratch --exclude .deps \ + koch@ftp.guug.de:work/gnupg . cvs-put: - rsync -Cavuzb . koch@ftp.guug.de:work/gnupg + rsync -Cavuzb --exclude .deps --exclude scratch \ + . koch@ftp.guug.de:work/gnupg cvs-sync: cvs-get cvs-put +tobold-get: + rsync -Cavuzb --exclude scratch --exclude .deps \ + tobold:gnupg/ . + +tobold-put: + rsync -Cavuzb --excude scratch --exclude .deps \ + . tobold:gnupg/ + + .PHONY: cvs-get cvs-put cvs-sync diff --git a/NEWS b/NEWS index 1e359d035..17d0330e4 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ keys. Use "--keyring gnupg-gdbm:". This is not (yet) supported for secret keys. + * A Russian language file in the distribution (alternatives are in + the contrib directory of the FTP servers) + + Noteworthy changes in version 0.4.2 ----------------------------------- diff --git a/TODO b/TODO index a17096a7e..e891645ae 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,8 @@ * Fix ;) revocation and expire stuff. + * check preferences (cipher and compress) + * OpenBSD: dynamic loading with dlopen works on OpenBSD, but: OpenBSD binaries are a.out, so every symbol begins with "_" diff --git a/checks/ChangeLog b/checks/ChangeLog index 4d99d8629..3b87c65e6 100644 --- a/checks/ChangeLog +++ b/checks/ChangeLog @@ -1,3 +1,8 @@ +Sun Oct 25 18:19:35 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mds.test: Check whether TIGER is available. + * sigs.tesr: Ditto. + Wed Sep 23 12:25:07 1998 Werner Koch (wk@isil.d.shuttle.de) * run-gpg.patterns: New (because Solaris fgrep does not like -f -). diff --git a/checks/defs.inc b/checks/defs.inc index 49cbcf292..8e754a7bc 100755 --- a/checks/defs.inc +++ b/checks/defs.inc @@ -60,6 +60,10 @@ chdir () { #} +have_hash_algo () { + ../g10/gpgm --homedir . --version | grep "Hash:.*$1" >/dev/null +} + set -e pgmname=`basename $0` #trap cleanup SIGHUP SIGINT SIGQUIT diff --git a/checks/mds.test b/checks/mds.test index f945a6cbf..2d04812d4 100755 --- a/checks/mds.test +++ b/checks/mds.test @@ -1,7 +1,9 @@ #!/bin/sh + . $srcdir/defs.inc || exit 3 + test_one () { if [ "`grep $1 y | sed -e 's/.*=[ ]\(.*\)/\1/' -e 's/ //g'`" != "$2" ]; then failed="$failed $1" @@ -11,11 +13,15 @@ test_one () { failed="" #info Checking message digests -echo -n "" | $srcdir/run-gpgm --print-mds >y +echo -n "" | $srcdir/run-gpgm -v --print-mds >y test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E" test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31" -test_one "TIGER" "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A" +if have_hash_algo "TIGER"; then + test_one "TIGER" "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A" +else + echo "Hash algorithm TIGER/192 is not installed" +fi [ "$failed" != "" ] && error "$failed failed for empty string" @@ -23,7 +29,9 @@ echo -n "abcdefghijklmnopqrstuvwxyz" | $srcdir/run-gpgm --print-mds >y test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B" test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89" test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC" -test_one "TIGER" "307DE5EE72A414172A0355CCBF120404E9EE7BF32F60110B" +if have_hash_algo "TIGER"; then + test_one "TIGER" "307DE5EE72A414172A0355CCBF120404E9EE7BF32F60110B" +fi [ "$failed" != "" ] && error "$failed failed for a..z" diff --git a/checks/sigs.test b/checks/sigs.test index 2446dde96..a32388948 100755 --- a/checks/sigs.test +++ b/checks/sigs.test @@ -9,7 +9,12 @@ for i in $plain_files $data_files; do cmp $i y || error "$i: mismatch" done -for da in ripemd160 sha1 md5 tiger; do +hash_algo_list="ripemd160 sha1 md5" +if have_hash_algo "TIGER"; then + hash_algo_list="$hash_algo_list tiger" +fi + +for da in $hash_algo_list ; do for i in $plain_files; do echo "$usrpass1" | $srcdir/run-gpg --passphrase-fd 0 --digest-algo $da \ -s -o x --yes $i diff --git a/configure.in b/configure.in index 93ef19d0a..a497b3da9 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ AM_CONFIG_HEADER(config.h) VERSION=`cat $srcdir/VERSION` PACKAGE=gnupg -ALL_LINGUAS="en de it fr" +ALL_LINGUAS="en de it fr ru" AC_SUBST(VERSION) AC_SUBST(PACKAGE) AC_DEFINE_UNQUOTED(VERSION, "$VERSION") diff --git a/doc/gpg.1pod b/doc/gpg.1pod index 91daea323..2b6724088 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -190,8 +190,10 @@ B<--export-secret-keys> [I Same as B<--export>, but does export the secret keys. This is normally not very useful. -B<--import> - import/merge keys +B<--import>, B<--fast-import> + Import/merge keys. The fast version does not build + the trustdb; this can be deon at anytime with the + command B<--update-trustdb>. B<--export-ownertrust> List the assigned ownertrust values in ascii format @@ -238,6 +240,8 @@ B<-v>, B<--verbose> Give more information during processing. If used twice, the input data is listed in detail. +B<-q>, B<--quiet> + Be somewhat more quiet in some cases. B<-z> I Set compress level to I. A value of 0 for I @@ -260,10 +264,10 @@ B<--no-batch> is used in the options file. B<--yes> - Assume yes on most questions. + Assume "yes" on most questions. B<--no> - Assume no on most questions. + Assume "no" on most questions. B<--keyring> I Add I to the list of keyrings. @@ -271,6 +275,9 @@ B<--keyring> I are replaced by the HOME directory. If the filename does not contain a slash, it is assumed to be in the home-directory (F<~/.gnupg> if B<--homedir>) is not used. + The filename may be prefixed with a scheme: + "gnupg-ring:" is the default one. + "gnupg-gdbm:" may be used for a GDBM ring. B<--secret-keyring> I Same as B<--keyring> but for secret keyrings. diff --git a/g10/ChangeLog b/g10/ChangeLog index f16a600b6..35afefa16 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,52 @@ +Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * openfile.c (copy_options_File): New. + * ringedit.c (add_keyblock_resource): Creates options file + * tdbio.c (tdbio_set_dbname): Ditto. + +Sat Oct 24 14:10:53 1998 brian moore + + * mainproc.c (proc_pubkey_enc): Don't release the DEK + (do_proc_packets): Ditto. + +Fri Oct 23 06:49:38 1998 me,,, (wk@tobold) + + * keyedit.c (keyedit_menu): Comments are now allowed + + * trustdb.c: Rewrote large parts. + + +Thu Oct 22 15:56:45 1998 Michael Roth (mroth@nessie.de) + + * encode.c: (encode_simple): Only the plain filename without + a given directory is stored in generated packets. + (encode_crypt): Ditto. + + * sign.c: (sign_file) Ditto. + + +Thu Oct 22 10:53:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * trustdb.c (update_trust_record): Add new optional arg. + + * import.c (import_keys): Add statistics output + * trustdb.c (update_trustdb): Ditto. + (insert_trustdb): Ditto. + + * tdbio.c (tdbio_begin_transaction): New. + (tdbio_end_transaction): New. + (tdbio_cancel_transaction): New. + + * g10.c (main): New option --quit. + + * trustdb.c (check_hint_sig): No tests for user-id w/o sig. + This caused an assert while checking the sigs. + + * trustdb.c (upd_sig_record): Splitted into several functions. + + * import.c (import_keys): New arg "fast". + * g10.c (main): New command --fast-import. + Wed Oct 21 18:19:36 1998 Michael Roth * ringedit.c (add_keyblock_resource): Directory is now created. diff --git a/g10/Makefile.am b/g10/Makefile.am index 75838524a..02e3ee525 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -EXTRA_DIST = OPTIONS pubring.asc +EXTRA_DIST = OPTIONS pubring.asc options.skel OMIT_DEPENDENCIES = zlib.h zconf.h LDFLAGS = @LDFLAGS@ @DYNLINK_LDFLAGS@ needed_libs = ../cipher/libcipher.a ../mpi/libmpi.a ../util/libutil.a @@ -87,3 +87,9 @@ g10maint.o: $(srcdir)/g10.c $(PROGRAMS): $(needed_libs) +install-data-local: + $(mkinstalldirs) $(pkgdatadir) + $(INSTALL_DATA) $(srcdir)/options.skel $(pkgdatadir)/options.skel + + + diff --git a/g10/encode.c b/g10/encode.c index 0d8a84c94..371a23731 100644 --- a/g10/encode.c +++ b/g10/encode.c @@ -140,10 +140,11 @@ encode_simple( const char *filename, int mode ) /* setup the inner packet */ if( filename || opt.set_filename ) { - const char *s = opt.set_filename ? opt.set_filename : filename; + char *s = make_basename( opt.set_filename ? opt.set_filename : filename ); pt = m_alloc( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); + m_free(s); } else { /* no filename */ pt = m_alloc( sizeof *pt - 1 ); @@ -253,10 +254,11 @@ encode_crypt( const char *filename, STRLIST remusr ) /* setup the inner packet */ if( filename || opt.set_filename ) { - const char *s = opt.set_filename ? opt.set_filename : filename; + char *s = make_basename( opt.set_filename ? opt.set_filename : filename ); pt = m_alloc( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); + m_free(s); } else { /* no filename */ pt = m_alloc( sizeof *pt - 1 ); diff --git a/g10/g10.c b/g10/g10.c index 84ddf5a8a..3df9121b5 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -57,6 +57,7 @@ enum cmd_and_opt_values { aNull = 0, oKOption = 'k', oDryRun = 'n', oOutput = 'o', + oQuiet = 'q', oRemote = 'r', aSign = 's', oTextmode = 't', @@ -76,6 +77,7 @@ enum cmd_and_opt_values { aNull = 0, aKMode, aKModeC, aImport, + aFastImport, aVerify, aListKeys, aListSigs, @@ -174,6 +176,7 @@ static ARGPARSE_OPTS opts[] = { { aExport, "export" , 256, N_("export keys") }, { aExportSecret, "export-secret-keys" , 256, "@" }, { aImport, "import", 256 , N_("import/merge keys")}, + { aFastImport, "fast-import", 256 , "@"}, { aListPackets, "list-packets",256,N_("list only the sequence of packets")}, #ifdef IS_G10MAINT { aExportOwnerTrust, @@ -206,6 +209,7 @@ static ARGPARSE_OPTS opts[] = { #endif { oOutput, "output", 2, N_("use as output file")}, { oVerbose, "verbose", 0, N_("verbose") }, + { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") }, /* { oDryRun, "dry-run", 0, N_("do not make any changes") }, */ { oBatch, "batch", 0, N_("batch mode: never ask")}, @@ -614,6 +618,7 @@ main( int argc, char **argv ) case aCheckKeys: set_cmd( &cmd, aCheckKeys); break; case aListPackets: set_cmd( &cmd, aListPackets); break; case aImport: set_cmd( &cmd, aImport); break; + case aFastImport: set_cmd( &cmd, aFastImport); break; case aExport: set_cmd( &cmd, aExport); break; case aListKeys: set_cmd( &cmd, aListKeys); break; case aListSigs: set_cmd( &cmd, aListSigs); break; @@ -657,6 +662,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 oVerbose: g10_opt_verbose++; opt.verbose++; opt.list_sigs=1; break; case oKOption: set_cmd( &cmd, aKMode ); break; @@ -1022,14 +1028,15 @@ main( int argc, char **argv ) break; #endif + case aFastImport: case aImport: if( !argc ) { - rc = import_keys( NULL ); + rc = import_keys( NULL, (cmd == aFastImport) ); if( rc ) log_error("import failed: %s\n", g10_errstr(rc) ); } for( ; argc; argc--, argv++ ) { - rc = import_keys( *argv ); + rc = import_keys( *argv, (cmd == aFastImport) ); if( rc ) log_error("import from '%s' failed: %s\n", *argv, g10_errstr(rc) ); diff --git a/g10/import.c b/g10/import.c index 374843363..075ecd358 100644 --- a/g10/import.c +++ b/g10/import.c @@ -36,9 +36,24 @@ #include "i18n.h" +static struct { + ulong no_user_id; + ulong imported; + ulong imported_rsa; + ulong n_uids; + ulong n_sigs; + ulong n_subk; + ulong unchanged; + ulong n_revoc; + ulong secret_read; + ulong secret_imported; + ulong secret_dups; +} stats; + + static int read_block( IOBUF a, compress_filter_context_t *cfx, PACKET **pending_pkt, KBNODE *ret_root ); -static int import_one( const char *fname, KBNODE keyblock ); +static int import_one( const char *fname, KBNODE keyblock, int fast ); static int import_secret_one( const char *fname, KBNODE keyblock ); static int import_revoke_cert( const char *fname, KBNODE node ); static int chk_self_sigs( const char *fname, KBNODE keyblock, @@ -59,7 +74,7 @@ static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, * least one userid. Only user ids which are self signed will be imported. * Other signatures are not checked. * - * Actually this functtion does a merge. It works like this: + * Actually this function does a merge. It works like this: * * - get the keyblock * - check self-signatures and remove all userids and their signatures @@ -85,7 +100,7 @@ static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs, * */ int -import_keys( const char *fname ) +import_keys( const char *fname, int fast ) { armor_filter_context_t afx; compress_filter_context_t cfx; @@ -93,11 +108,15 @@ import_keys( const char *fname ) IOBUF inp = NULL; KBNODE keyblock; int rc = 0; + ulong count=0; memset( &afx, 0, sizeof afx); memset( &cfx, 0, sizeof cfx); afx.only_keyblocks = 1; + /* fixme: don't use static variables */ + memset( &stats, 0, sizeof( stats ) ); + /* open file */ inp = iobuf_open(fname); if( !fname ) @@ -112,7 +131,7 @@ import_keys( const char *fname ) while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) { if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY ) - rc = import_one( fname, keyblock ); + rc = import_one( fname, keyblock, fast ); else if( keyblock->pkt->pkttype == PKT_SECRET_KEY ) rc = import_secret_one( fname, keyblock ); else if( keyblock->pkt->pkttype == PKT_SIGNATURE @@ -125,12 +144,41 @@ import_keys( const char *fname ) release_kbnode(keyblock); if( rc ) break; + if( !(++count % 100) ) + log_info(_("%lu keys so far processed\n"), count ); } if( rc == -1 ) rc = 0; else if( rc && rc != G10ERR_INV_KEYRING ) log_error_f( fname, _("read error: %s\n"), g10_errstr(rc)); + log_info(_("Total number processed: %lu\n"), count ); + if( stats.no_user_id ) + log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id ); + if( stats.imported || stats.imported_rsa ) { + log_info(_(" imported: %lu"), stats.imported ); + if( stats.imported_rsa ) + fprintf(stderr, " (RSA: %lu)", stats.imported_rsa ); + putc('\n', stderr); + } + if( stats.unchanged ) + log_info(_(" unchanged: %lu\n"), stats.unchanged ); + if( stats.n_uids ) + log_info(_(" new user IDs: %lu\n"), stats.n_uids ); + if( stats.n_subk ) + log_info(_(" new subkeys: %lu\n"), stats.n_subk ); + if( stats.n_sigs ) + log_info(_(" new signatures: %lu\n"), stats.n_sigs ); + if( stats.n_revoc ) + log_info(_(" new key revocations: %lu\n"), stats.n_revoc ); + if( stats.secret_read ) + log_info(_(" secret keys read: %lu\n"), stats.secret_read ); + if( stats.secret_imported ) + log_info(_(" secret keys imported: %lu\n"), stats.secret_imported ); + if( stats.secret_dups ) + log_info(_(" secret keys unchanged: %lu\n"), stats.secret_dups ); + + iobuf_close(inp); return rc; } @@ -238,7 +286,7 @@ read_block( IOBUF a, compress_filter_context_t *cfx, * which called g10. */ static int -import_one( const char *fname, KBNODE keyblock ) +import_one( const char *fname, KBNODE keyblock, int fast ) { PKT_public_key *pk; PKT_public_key *pk_orig; @@ -280,9 +328,12 @@ import_one( const char *fname, KBNODE keyblock ) return rc== -1? 0:rc; if( !delete_inv_parts( fname, keyblock, keyid ) ) { - log_info_f( fname, _("key %08lX: no valid user ids\n"), - (ulong)keyid[1]); - log_info(_("this may be caused by a missing self-signature\n")); + if( !opt.quiet ) { + log_info_f( fname, _("key %08lX: no valid user ids\n"), + (ulong)keyid[1]); + log_info(_("this may be caused by a missing self-signature\n")); + } + stats.no_user_id++; return 0; } @@ -311,7 +362,12 @@ import_one( const char *fname, KBNODE keyblock ) _("can't write to keyring: %s\n"), g10_errstr(rc) ); unlock_keyblock( &kbpos ); /* we are ready */ - log_info_f( fname, _("key %08lX: public key imported\n"), (ulong)keyid[1]); + if( !opt.quiet ) + log_info_f( fname, _("key %08lX: public key imported\n"), + (ulong)keyid[1]); + stats.imported++; + if( is_RSA( pk->pubkey_algo ) ) + stats.imported_rsa++; new_key = 1; } else { /* merge */ @@ -366,29 +422,39 @@ import_one( const char *fname, KBNODE keyblock ) _("can't write keyblock: %s\n"), g10_errstr(rc) ); unlock_keyblock( &kbpos ); /* we are ready */ - if( n_uids == 1 ) - log_info_f(fname, _("key %08lX: 1 new user-id\n"), - (ulong)keyid[1]); - else if( n_uids ) - log_info_f(fname, _("key %08lX: %d new user-ids\n"), - (ulong)keyid[1], n_uids ); - if( n_sigs == 1 ) - log_info_f(fname, _("key %08lX: 1 new signature\n"), - (ulong)keyid[1]); - else if( n_sigs ) - log_info_f(fname, _("key %08lX: %d new signatures\n"), - (ulong)keyid[1], n_sigs ); - if( n_subk == 1 ) - log_info_f(fname, _("key %08lX: 1 new subkey\n"), - (ulong)keyid[1]); - else if( n_subk ) - log_info_f(fname, _("key %08lX: %d new subkeys\n"), - (ulong)keyid[1], n_subk ); + if( !opt.quiet ) { + if( n_uids == 1 ) + log_info_f(fname, _("key %08lX: 1 new user-id\n"), + (ulong)keyid[1]); + else if( n_uids ) + log_info_f(fname, _("key %08lX: %d new user-ids\n"), + (ulong)keyid[1], n_uids ); + if( n_sigs == 1 ) + log_info_f(fname, _("key %08lX: 1 new signature\n"), + (ulong)keyid[1]); + else if( n_sigs ) + log_info_f(fname, _("key %08lX: %d new signatures\n"), + (ulong)keyid[1], n_sigs ); + if( n_subk == 1 ) + log_info_f(fname, _("key %08lX: 1 new subkey\n"), + (ulong)keyid[1]); + else if( n_subk ) + log_info_f(fname, _("key %08lX: %d new subkeys\n"), + (ulong)keyid[1], n_subk ); + } + + stats.n_uids +=n_uids; + stats.n_sigs +=n_sigs; + stats.n_subk +=n_subk; + } + else { + if( !opt.quiet ) + log_info_f(fname, _("key %08lX: not changed\n"), + (ulong)keyid[1] ); + stats.unchanged++; } - else - log_info_f(fname, _("key %08lX: not changed\n"), (ulong)keyid[1] ); } - if( !rc ) { + if( !rc && !fast ) { rc = query_trust_record( new_key? pk : pk_orig ); if( rc && rc != -1 ) log_error("trustdb error: %s\n", g10_errstr(rc) ); @@ -399,7 +465,7 @@ import_one( const char *fname, KBNODE keyblock ) (ulong)keyid[1], g10_errstr(rc) ); } else if( mod_key ) - rc = update_trust_record( keyblock_orig ); + rc = update_trust_record( keyblock_orig, NULL ); else rc = clear_trust_checked_flag( new_key? pk : pk_orig ); } @@ -442,6 +508,7 @@ import_secret_one( const char *fname, KBNODE keyblock ) uidnode->pkt->pkt.user_id->len, 0 ); putc('\n', stderr); } + stats.secret_read++; if( !uidnode ) { log_error_f(fname, _("key %08lX: no user id\n"), (ulong)keyid[1]); return 0; @@ -468,10 +535,12 @@ import_secret_one( const char *fname, KBNODE keyblock ) unlock_keyblock( &kbpos ); /* we are ready */ log_info_f(fname, _("key %08lX: secret key imported\n"), (ulong)keyid[1]); + stats.secret_imported++; } else if( !rc ) { /* we can't merge secret keys */ log_error_f(fname, _("key %08lX: already in secret keyring\n"), (ulong)keyid[1]); + stats.secret_dups++; } else log_error_f(fname, _("key %08lX: secret key not found: %s\n"), @@ -569,8 +638,10 @@ import_revoke_cert( const char *fname, KBNODE node ) _("can't write keyblock: %s\n"), g10_errstr(rc) ); unlock_keyblock( &kbpos ); /* we are ready */ - log_info_f(fname, _("key %08lX: revocation certificate imported\n"), + if( !opt.quiet ) + log_info_f(fname, _("key %08lX: revocation certificate imported\n"), (ulong)keyid[1]); + stats.n_revoc++; leave: release_kbnode( keyblock ); diff --git a/g10/keyedit.c b/g10/keyedit.c index a504d06c7..62921349c 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -571,10 +571,12 @@ keyedit_menu( const char *username, STRLIST locusr ) tty_printf("\n"); redisplay = 0; } - m_free(answer); - answer = cpr_get(N_("keyedit.cmd"), _("Command> ")); - cpr_kill_prompt(); - trim_spaces(answer); + do { + m_free(answer); + answer = cpr_get(N_("keyedit.cmd"), _("Command> ")); + cpr_kill_prompt(); + trim_spaces(answer); + } while( *answer == '#' ); arg_number = 0; if( !*answer ) @@ -645,7 +647,7 @@ keyedit_menu( const char *username, STRLIST locusr ) } else tty_printf(_("Key not changed so no update needed.\n")); - rc = update_trust_record( keyblock ); + rc = update_trust_record( keyblock, NULL ); if( rc ) log_error(_("update of trust db failed: %s\n"), g10_errstr(rc) ); @@ -703,7 +705,7 @@ keyedit_menu( const char *username, STRLIST locusr ) sec_modified = modified = 1; /* must update the trustdb already here, so that preferences * get listed correctly */ - rc = update_trust_record( keyblock ); + rc = update_trust_record( keyblock, NULL ); if( rc ) { log_error(_("update of trust db failed: %s\n"), g10_errstr(rc) ); diff --git a/g10/main.h b/g10/main.h index 7cde3c58a..ddf7086e9 100644 --- a/g10/main.h +++ b/g10/main.h @@ -88,6 +88,7 @@ int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); int overwrite_filep( const char *fname ); int open_outfile( const char *iname, int mode, IOBUF *a ); IOBUF open_sigfile( const char *iname ); +void copy_options_file( const char *destdir ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); @@ -100,7 +101,7 @@ KBNODE make_comment_node( const char *s ); KBNODE make_mpi_comment_node( const char *s, MPI a ); /*-- import.c --*/ -int import_keys( const char *filename ); +int import_keys( const char *filename, int fast ); /*-- export.c --*/ int export_pubkeys( STRLIST users ); int export_seckeys( STRLIST users ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 7980c22dc..a075f836f 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -180,11 +180,12 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) if( is_ELGAMAL(enc->pubkey_algo) || enc->pubkey_algo == PUBKEY_ALGO_DSA || is_RSA(enc->pubkey_algo) ) { - m_free(c->dek ); /* paranoid: delete a pending DEK */ - c->dek = m_alloc_secure( sizeof *c->dek ); - if( (result = get_session_key( enc, c->dek )) ) { - /* error: delete the DEK */ - m_free(c->dek); c->dek = NULL; + if ( !c->dek ) { + c->dek = m_alloc_secure( sizeof *c->dek ); + if( (result = get_session_key( enc, c->dek )) ) { + /* error: delete the DEK */ + m_free(c->dek); c->dek = NULL; + } } } else @@ -716,13 +717,6 @@ do_proc_packets( CTX c, IOBUF a ) c->iobuf = a; init_packet(pkt); while( (rc=parse_packet(a, pkt)) != -1 ) { - /* cleanup if we have an illegal data structure */ - if( c->dek && pkt->pkttype != PKT_ENCRYPTED ) { - /* FIXME: do we need to ave it in case we have no secret - * key for one of the next reciepents- we should check it - * here. */ - m_free(c->dek); c->dek = NULL; /* burn it */ - } if( rc ) { free_packet(pkt); diff --git a/g10/openfile.c b/g10/openfile.c index 763ac2f9a..0dff81bac 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -78,11 +78,11 @@ open_outfile( const char *iname, int mode, IOBUF *a ) *a = NULL; if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) { if( !(*a = iobuf_create(NULL)) ) { - log_error("can't open [stdout]: %s\n", strerror(errno) ); + log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) ); rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) - log_info("writing to stdout\n"); + log_info(_("writing to stdout\n")); } else { char *buf=NULL; @@ -98,11 +98,11 @@ open_outfile( const char *iname, int mode, IOBUF *a ) } if( overwrite_filep( name ) ) { if( !(*a = iobuf_create( name )) ) { - log_error("can't create %s: %s\n", name, strerror(errno) ); + log_error(_("%s: can't create: %s\n"), name, strerror(errno) ); rc = G10ERR_CREATE_FILE; } else if( opt.verbose ) - log_info("writing to '%s'\n", name ); + log_info(_("writing to '%s'\n"), name ); } else rc = G10ERR_FILE_EXISTS; @@ -131,10 +131,54 @@ open_sigfile( const char *iname ) buf[len-4] = 0 ; a = iobuf_open( buf ); if( opt.verbose ) - log_info("assuming signed data in '%s'\n", buf ); + log_info(_("assuming signed data in '%s'\n"), buf ); m_free(buf); } } return a; } + +/**************** + * Copy the option file skeleton to the given directory. + */ +void +copy_options_file( const char *destdir ) +{ + const char *datadir = GNUPG_DATADIR; + char *fname; + FILE *src, *dst; + int linefeeds=0; + int c; + + fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 ); + strcpy(stpcpy(fname, datadir), "/options.skel" ); + src = fopen( fname, "r" ); + if( !src ) { + log_error(_("%s: can't open: %s\n"), fname, strerror(errno) ); + m_free(fname); + return; + } + strcpy(stpcpy(fname, destdir), "/options" ); + dst = fopen( fname, "w" ); + if( !dst ) { + log_error(_("%s: can't create: %s\n"), fname, strerror(errno) ); + fclose( src ); + m_free(fname); + return; + } + + while( (c=getc(src)) != EOF ) { + if( linefeeds < 3 ) { + if( c == '\n' ) + linefeeds++; + } + else + putc( c, dst ); + } + fclose( dst ); + fclose( src ); + log_info(_("%s: new options file created\n"), fname ); + m_free(fname); +} + diff --git a/g10/options.h b/g10/options.h index 09a33016c..0ad465177 100644 --- a/g10/options.h +++ b/g10/options.h @@ -26,6 +26,7 @@ struct { int verbose; + int quiet; unsigned debug; int armor; int compress; diff --git a/g10/options.skel b/g10/options.skel new file mode 100644 index 000000000..009ce9d01 --- /dev/null +++ b/g10/options.skel @@ -0,0 +1,37 @@ +These first three lines are not copied to the options file in +the users home directory. +$Id$ +# Options for GnuPG +# +# Unless you you specify which option file to use (with the +# commandline option "--options filename"), GnuPG uses the +# file ~/.gnupg/options by default. +# +# An option file can contain all long options which are +# available in GnuPG. If the first non white space character of +# a line is a '#', this line is ignored. Empty lines are also +# ignored. +# +# See the man page for a list of options. + +# Uncomment the next line to get rid of the copyright notice +#no-greeting + +# If you have more than 1 secret key in your keyring, you may want +# to uncomment the following option and set your preffered keyid + +# default-key 621CC013 + +# The next option is enabled because this one is needed for interoperation +# with PGP 5 users. To enable full OpenPGP compliance you have to remove +# this option. + +force-v3-sigs + +# Default is to use the newer compress algo 2, but PGP 5 does not +# like this, so we use the old one +# Hmm: Do we really need this ... preferences should decide which compress +# algo to use. + +compress-algo 1 + diff --git a/g10/ringedit.c b/g10/ringedit.c index e414d0513..c7d1d8bb5 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -59,6 +59,7 @@ #include "keydb.h" #include "host2net.h" #include "options.h" +#include "main.h" #include "i18n.h" @@ -153,7 +154,7 @@ add_keyblock_resource( const char *url, int force, int secret ) { static int any_secret, any_public; const char *resname = url; - IOBUF iobuf; + IOBUF iobuf = NULL; int i; char *filename = NULL; int rc = 0; @@ -217,6 +218,8 @@ add_keyblock_resource( const char *url, int force, int secret ) else rt = rt_RING; } + else /* maybe empty: assume ring */ + rt = rt_RING; fclose( fp ); } else /* no file yet: create ring */ @@ -258,6 +261,7 @@ add_keyblock_resource( const char *url, int force, int secret ) } else log_info( _("%s: directory created\n"), filename ); + copy_options_file( filename ); } else { @@ -513,6 +517,7 @@ locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen ); break; default: + rc = G10ERR_UNSUPPORTED; break; } @@ -521,7 +526,7 @@ locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) kbpos->fp = NULL; return 0; } - else if( rc != -1 ) { + else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { log_error("error searching resource %d: %s\n", i, g10_errstr(rc)); last_rc = rc; @@ -551,6 +556,7 @@ locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret ) rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid ); break; default: + rc = G10ERR_UNSUPPORTED; break; } @@ -559,7 +565,7 @@ locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret ) kbpos->fp = NULL; return 0; } - else if( rc != -1 ) { + else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) { log_error("error searching resource %d: %s\n", i, g10_errstr(rc)); last_rc = rc; @@ -719,7 +725,10 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) break; case rt_GDBM: break; - default: BUG(); + default: + log_error("OOPS in close enum_keyblocks - ignored\n"); + return rc; + break; } /* release pending packet */ free_packet( kbpos->pkt ); @@ -778,7 +787,8 @@ delete_keyblock( KBPOS *kbpos ) break; #ifdef HAVE_LIBGDBM case rt_GDBM: - /* FIXME!!!! */ + log_debug("deleting gdbm keyblock is not yet implemented\n"); + rc = 0; break; #endif default: BUG(); diff --git a/g10/sign.c b/g10/sign.c index 1f4e1ce65..db5272e53 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -253,7 +253,7 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, int skcount=0; /* loop over the secret certificates and build headers * The specs now say that the data should be bracket by - * the onepass-sig and signature-packet; so we muts build it + * the onepass-sig and signature-packet; so we must build it * here in reverse order */ for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) skcount++; @@ -320,10 +320,11 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, } else { if( fname || opt.set_filename ) { - const char *s = opt.set_filename ? opt.set_filename : fname; + char *s = make_basename( opt.set_filename ? opt.set_filename : fname ); pt = m_alloc( sizeof *pt + strlen(s) - 1 ); pt->namelen = strlen(s); memcpy(pt->name, s, pt->namelen ); + m_free(s); } else { /* no filename */ pt = m_alloc( sizeof *pt - 1 ); diff --git a/g10/tdbio.c b/g10/tdbio.c index 76e606e0e..1954929ae 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -56,9 +56,11 @@ struct cache_ctrl_struct { char data[TRUST_RECORD_LEN]; }; -#define MAX_CACHE_ENTRIES 200 +#define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased due while in a */ +#define MAX_CACHE_ENTRIES_HARD 1000 /* transaction to this one */ static CACHE_CTRL cache_list; static int cache_entries; +static int cache_is_dirty; /* a type used to pass infomation to cmp_krec_fpr */ struct cmp_krec_fpr_struct { @@ -76,6 +78,7 @@ struct cmp_sdir_struct { static char *db_name; static int db_fd = -1; +static int in_transaction; static void open_db(void); @@ -143,8 +146,10 @@ put_record_into_cache( ulong recno, const char *data ) else if( r->recno == recno ) { if( !r->flags.dirty ) { /* Hmmm: should we use a a copy and compare? */ - if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) + if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) { r->flags.dirty = 1; + cache_is_dirty = 1; + } } memcpy( r->data, data, TRUST_RECORD_LEN ); return 0; @@ -163,11 +168,12 @@ put_record_into_cache( ulong recno, const char *data ) r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); r->flags.dirty = 1; + cache_is_dirty = 1; cache_entries++; return 0; } /* see whether we reached the limit */ - if( cache_entries < MAX_CACHE_ENTRIES ) { /* no */ + if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */ r = m_alloc( sizeof *r ); r->flags.used = 1; r->recno = recno; @@ -175,6 +181,7 @@ put_record_into_cache( ulong recno, const char *data ) r->flags.dirty = 1; r->next = cache_list; cache_list = r; + cache_is_dirty = 1; cache_entries++; return 0; } @@ -199,10 +206,31 @@ put_record_into_cache( ulong recno, const char *data ) r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); r->flags.dirty = 1; + cache_is_dirty = 1; cache_entries++; return 0; } /* no clean entries: have to flush some dirty entries */ + if( in_transaction ) { + /* but we can't do this while in a transaction + * we increase the cache size instead */ + if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */ + if( !(cache_entries % 100) ) + log_info("increasing tdbio cache size\n"); + r = m_alloc( sizeof *r ); + r->flags.used = 1; + r->recno = recno; + memcpy( r->data, data, TRUST_RECORD_LEN ); + r->flags.dirty = 1; + r->next = cache_list; + cache_list = r; + cache_is_dirty = 1; + cache_entries++; + return 0; + } + log_info("hard cache size limit reached\n"); + return G10ERR_RESOURCE_LIMIT; + } if( dirty_count ) { int n = dirty_count / 5; /* discard some dirty entries */ if( !n ) @@ -226,6 +254,7 @@ put_record_into_cache( ulong recno, const char *data ) r->recno = recno; memcpy( r->data, data, TRUST_RECORD_LEN ); r->flags.dirty = 1; + cache_is_dirty = 1; cache_entries++; return 0; } @@ -233,16 +262,27 @@ put_record_into_cache( ulong recno, const char *data ) } +int +tdbio_is_dirty() +{ + return cache_is_dirty; +} + /**************** - * Sync the cache to disk + * Flush the cache. This cannot be used while in a transaction. */ - int tdbio_sync() { CACHE_CTRL r; + if( in_transaction ) + log_bug("tdbio: syncing while in transaction\n"); + + if( !cache_is_dirty ) + return 0; + for( r = cache_list; r; r = r->next ) { if( r->flags.used && r->flags.dirty ) { int rc = write_cache_item( r ); @@ -250,6 +290,63 @@ tdbio_sync() return rc; } } + cache_is_dirty = 0; + return 0; +} + + + +/**************** + * Simple transactions system: + * Everything between begin_transaction and end/cancel_transaction + * is not immediatly written but at the time of end_transaction. + * + */ +int +tdbio_begin_transaction() +{ + int rc; + + if( in_transaction ) + log_bug("tdbio: nested transactions\n"); + /* flush everything out */ + rc = tdbio_sync(); + if( rc ) + return rc; + in_transaction = 1; + return 0; +} + +int +tdbio_end_transaction() +{ + if( !in_transaction ) + log_bug("tdbio: no active transaction\n"); + in_transaction = 0; + return tdbio_sync(); +} + +int +tdbio_cancel_transaction() +{ + CACHE_CTRL r; + + if( !in_transaction ) + log_bug("tdbio: no active transaction\n"); + + /* remove all dirty marked entries, so that the original ones + * are read back the next time */ + if( cache_is_dirty ) { + for( r = cache_list; r; r = r->next ) { + if( r->flags.used && r->flags.dirty ) { + r->flags.used = 0; + cache_entries--; + } + } + cache_is_dirty = 0; + } + + in_transaction = 0; return 0; } @@ -293,6 +390,7 @@ tdbio_set_dbname( const char *new_dbname, int create ) fname, strerror(errno) ); else log_info( _("%s: directory created\n"), fname ); + copy_options_file( fname ); } else log_fatal( _("%s: directory does not exist!\n"), fname ); diff --git a/g10/tdbio.h b/g10/tdbio.h index 68011d48f..e44f8c3e4 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -168,7 +168,11 @@ const char *tdbio_get_dbname(void); void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( TRUSTREC *rec ); +int tdbio_is_dirty(void); int tdbio_sync(void); +int tdbio_begin_transaction(void); +int tdbio_end_transaction(void); +int tdbio_cancel_transaction(void); int tdbio_delete_record( ulong recnum ); ulong tdbio_new_recnum(void); int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec ); diff --git a/g10/trustdb.c b/g10/trustdb.c index 5f391d028..7a6ec3bd1 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -65,7 +65,7 @@ struct trust_info { typedef struct trust_seg_list *TRUST_SEG_LIST; struct trust_seg_list { TRUST_SEG_LIST next; - int nseg; /* number of segmens */ + int nseg; /* number of segments */ int dup; TRUST_INFO seg[1]; /* segment list */ }; @@ -86,14 +86,9 @@ static LOCAL_ID_INFO *new_lid_table(void); static void release_lid_table( LOCAL_ID_INFO *tbl ); static int ins_lid_table_item( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); static int qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag ); -static void upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ); static void print_user_id( const char *text, u32 *keyid ); -static int do_list_path( TRUST_INFO *stack, int depth, int max_depth, - LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ); - static int list_sigs( ulong pubkey_id ); -static int propagate_trust( TRUST_SEG_LIST tslist ); static int do_check( TRUSTREC *drec, unsigned *trustlevel ); static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec ); @@ -102,8 +97,6 @@ static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec ); * which are the ones from our secrings */ static LOCAL_ID_INFO *ultikey_table; -static ulong last_trust_web_key; -static TRUST_SEG_LIST last_trust_web_tslist; #define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \ @@ -277,19 +270,6 @@ qry_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned *flag ) return -1; } -static void -upd_lid_table_flag( LOCAL_ID_INFO *tbl, ulong lid, unsigned flag ) -{ - LOCAL_ID_INFO a; - - for( a = tbl[lid & 0x0f]; a; a = a->next ) - if( a->lid == lid ) { - a->flag = flag; - return; - } - BUG(); -} - /**************** @@ -301,12 +281,19 @@ keyid_from_lid( ulong lid, u32 *keyid ) TRUSTREC rec; int rc; - rc = tdbio_read_record( lid, &rec, RECTYPE_DIR ); + rc = tdbio_read_record( lid, &rec, 0 ); if( rc ) { log_error("error reading dir record for LID %lu: %s\n", lid, g10_errstr(rc)); return G10ERR_TRUSTDB; } + if( rec.rectype == RECTYPE_SDIR ) + return 0; + if( rec.rectype != RECTYPE_DIR ) { + log_error("lid %lu: expected dir record, got type %d\n", + lid, rec.rectype ); + return G10ERR_TRUSTDB; + } if( !rec.r.dir.keylist ) { log_error("no primary key for LID %lu\n", lid ); return G10ERR_TRUSTDB; @@ -342,7 +329,6 @@ lid_from_keyblock( KBNODE keyblock ) - /**************** * Walk through the signatures of a public key. * The caller must provide a context structure, with all fields set @@ -364,9 +350,13 @@ walk_sigrecs( SIGREC_CONTEXT *c ) r = &c->ctl.rec; if( !c->ctl.init_done ) { c->ctl.init_done = 1; - read_record( c->lid, r, RECTYPE_DIR ); + read_record( c->lid, r, 0 ); + if( r->rectype != RECTYPE_DIR ) { + c->ctl.eof = 1; + return -1; /* return eof */ + } c->ctl.nextuid = r->r.dir.uidlist; - /* force a read (what a bad bad hack) */ + /* force a read */ c->ctl.index = SIGS_PER_RECORD; r->r.sig.next = 0; } @@ -503,17 +493,18 @@ print_user_id( const char *text, u32 *keyid ) m_free(p); } -static void + +static int print_keyid( FILE *fp, ulong lid ) { u32 ki[2]; if( keyid_from_lid( lid, ki ) ) - fprintf(fp, "????????.%lu", lid ); + return fprintf(fp, "????????.%lu", lid ); else - fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid ); + return fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid ); } -static void +static int print_trust( FILE *fp, unsigned trust ) { int c; @@ -525,14 +516,32 @@ print_trust( FILE *fp, unsigned trust ) case TRUST_MARGINAL: c = 'm'; break; case TRUST_FULLY: c = 'f'; break; case TRUST_ULTIMATE: c = 'u'; break; - default: fprintf(fp, "%02x", trust ); return; + default: fprintf(fp, "%02x", trust ); return 2; } putc(c, fp); + return 1; +} + + +static int +print_sigflags( FILE *fp, unsigned flags ) +{ + if( flags & SIGF_CHECKED ) { + fprintf(fp,"%c%c%c", + (flags & SIGF_VALID) ? 'V':'-', + (flags & SIGF_EXPIRED) ? 'E':'-', + (flags & SIGF_REVOKED) ? 'R':'-'); + } + else if( flags & SIGF_NOPUBKEY) + fputs("?--", fp); + else + fputs("---", fp); + return 3; } /* (a non-recursive algorithm would be easier) */ static int -do_list_sigs( ulong root, ulong pubkey, int depth, +do_list_sigs( ulong root, ulong pk_lid, int depth, LOCAL_ID_INFO *lids, unsigned *lineno ) { SIGREC_CONTEXT sx; @@ -540,26 +549,29 @@ do_list_sigs( ulong root, ulong pubkey, int depth, u32 keyid[2]; memset( &sx, 0, sizeof sx ); - sx.lid = pubkey; + sx.lid = pk_lid; for(;;) { rc = walk_sigrecs( &sx ); if( rc ) break; rc = keyid_from_lid( sx.sig_lid, keyid ); if( rc ) { - printf("%6u: %*s????????.%lu:%02x\n", *lineno, depth*4, "", - sx.sig_lid, sx.sig_flag ); + printf("%6u: %*s????????.%lu:", *lineno, depth*4, "", sx.sig_lid ); + print_sigflags( stdout, sx.sig_flag ); + putchar('\n'); ++*lineno; } else { - printf("%6u: %*s%08lX.%lu:%02x ", *lineno, depth*4, "", - (ulong)keyid[1], sx.sig_lid, sx.sig_flag ); - /* check whether we already checked this pubkey */ + printf("%6u: %*s%08lX.%lu:", *lineno, depth*4, "", + (ulong)keyid[1], sx.sig_lid ); + print_sigflags( stdout, sx.sig_flag ); + putchar(' '); + /* check whether we already checked this pk_lid */ if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) { print_user_id("[ultimately trusted]", keyid); ++*lineno; } - else if( sx.sig_lid == pubkey ) { + else if( sx.sig_lid == pk_lid ) { printf("[self-signature]\n"); ++*lineno; } @@ -632,7 +644,7 @@ list_records( ulong lid ) tdbio_dump_record( &dr, stdout ); for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) { - rc = tdbio_read_record( recno, &rec, RECTYPE_KEY ); + rc = tdbio_read_record( recno, &rec, 0 ); if( rc ) { log_error("lid %lu: read key record failed: %s\n", lid, g10_errstr(rc)); @@ -681,197 +693,241 @@ list_records( ulong lid ) /**************** - * Function to collect all trustpaths + * Given the directory record of a key, check whether we can + * find a path to an ultimately trusted key. We do this by + * checking all key signatures up to a some depth. */ static int -do_list_path( TRUST_INFO *stack, int depth, int max_depth, - LOCAL_ID_INFO *lids, TRUST_SEG_LIST *tslist ) +verify_key( int depth, int max_depth, TRUSTREC *drec ) { - SIGREC_CONTEXT sx; - unsigned last_depth; - int rc; + ulong rn, uidrn; + int marginal=0; + int fully=0; + size_t dbglen; - assert(depth); + /* Note: If used stack size is an issue, we could reuse the + * trustrec vars and reread them as needed */ - /*printf("%2lu/%d: scrutinizig\n", stack[depth-1], depth);*/ - if( depth >= max_depth || depth >= MAX_LIST_SIGS_DEPTH-1 ) { - /*printf("%2lu/%d: too deeply nested\n", stack[depth-1], depth);*/ - return 0; + dbglen = printf("verify_key: depth=%d %*s", depth, depth*3,"" ); + dbglen += print_keyid( stdout, drec->recnum ); + dbglen += printf(" ot="); + dbglen += print_trust(stdout, drec->r.dir.ownertrust ); + dbglen += printf(" -> "); + + if( depth >= max_depth ) { + /* max cert_depth reached */ + puts("undefined (too deep)"); + return TRUST_UNDEFINED; } - memset( &sx, 0, sizeof sx ); - sx.lid = stack[depth-1].lid; - /* loop over all signatures. If we do not have any, try to create them */ - while( !(rc = walk_sigrecs( &sx )) ) { - TRUST_SEG_LIST tsl, t2, tl; - int i; - - if( !(sx.sig_flag & SIGF_CHECKED) ) - continue; /* only checked sigs */ - if( !(sx.sig_flag & SIGF_VALID) ) - continue; /* and, of course, only valid sigs */ - if( (sx.sig_flag & SIGF_REVOKED) ) - continue; /* and skip revoked sigs */ - - stack[depth].lid = sx.sig_lid; - stack[depth].trust = 0; - if( qry_lid_table_flag( lids, sx.sig_lid, &last_depth) ) { - /*printf("%2lu/%d: marked\n", sx.sig_lid, depth );*/ - ins_lid_table_item( lids, sx.sig_lid, depth); - last_depth = depth; - } - else if( depth < last_depth ) { - /*printf("%2lu/%d: last_depth=%u - updated\n", sx.sig_lid, depth, last_depth);*/ - last_depth = depth; - upd_lid_table_flag( lids, sx.sig_lid, depth); - } - - if( last_depth < depth ) - /*printf("%2lu/%d: already visited\n", sx.sig_lid, depth)*/; - else if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) { - /* found end of path; store it, ordered by path length */ - tsl = m_alloc( sizeof *tsl + depth*sizeof(TRUST_INFO) ); - tsl->nseg = depth+1; - tsl->dup = 0; - for(i=0; i <= depth; i++ ) - tsl->seg[i] = stack[i]; - for(t2=*tslist,tl=NULL; t2; tl=t2, t2 = t2->next ) - if( depth < t2->nseg ) - break; - if( !tl ) { - tsl->next = t2; - *tslist = tsl; - } - else { - tsl->next = t2; - tl->next = tsl; - } - /*putchar('.'); fflush(stdout);*/ - /*printf("%2lu/%d: found\n", sx.sig_lid, depth);*/ - } - else { - rc = do_list_path( stack, depth+1, max_depth, lids, tslist); - if( rc && rc != -1 ) - break; - } + if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) { + /* we are at the end of a path */ + puts("ultimate"); + return TRUST_ULTIMATE; } - return rc==-1? 0 : rc; -} + /* loop over all user-ids */ + for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { + TRUSTREC rec; /* used for uids and sigs */ + ulong sigrn; -/**************** - * Make a list of trust paths - */ -static int -make_tsl( ulong lid, TRUST_SEG_LIST *ret_tslist ) -{ - int i, rc; - LOCAL_ID_INFO *lids = new_lid_table(); - TRUST_INFO stack[MAX_LIST_SIGS_DEPTH]; - TRUST_SEG_LIST tsl, tslist; - int max_depth = 4; + read_record( rn, &rec, RECTYPE_UID ); + uidrn = rec.r.uid.next; + /* fixme: continue if the uidrec is not marked valid */ - tslist = *ret_tslist = NULL; + /* loop over all signature records */ + for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { + int i; - if( !qry_lid_table_flag( ultikey_table, lid, NULL ) ) { - tslist = m_alloc( sizeof *tslist ); - tslist->nseg = 1; - tslist->dup = 0; - tslist->seg[0].lid = lid; - tslist->seg[0].trust = 0; - tslist->next = NULL; - rc = 0; - } - else { - stack[0].lid = lid; - stack[0].trust = 0; - rc = do_list_path( stack, 1, max_depth, lids, &tslist ); - } - if( !rc ) { /* wipe out duplicates */ - LOCAL_ID_INFO *work = new_lid_table(); - for( tsl=tslist; tsl; tsl = tsl->next ) { - for(i=1; i < tsl->nseg-1; i++ ) { - if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) { - tsl->dup = 1; /* mark as duplicate */ - break; + read_record( rn, &rec, RECTYPE_SIG ); + sigrn = rec.r.sig.next; + + for(i=0; i < SIGS_PER_RECORD; i++ ) { + TRUSTREC tmp; + int ot, nt; + + if( !rec.r.sig.sig[i].lid ) + continue; /* skip deleted sigs */ + if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) + continue; /* skip unchecked signatures */ + if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) + continue; /* skip invalid signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) + continue; /* skip expired signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) + continue; /* skip revoked signatures */ + /* fixme: skip duplicates */ + + read_record( rec.r.sig.sig[i].lid, &tmp, RECTYPE_DIR ); + ot = tmp.r.dir.ownertrust & TRUST_MASK; + #if 0 /* Does not work, because the owner trust of our + * own keys is not always set + * -- fix this in verify_own_keys() ? */ + if( ot < TRUST_MARGINAL ) { + printf(". "); + continue; /* ownertrust is too low; don't need to check */ + } + #endif + if( ot >= TRUST_FULLY ) + ot = TRUST_FULLY; /* just in case */ + + puts(""); + nt = verify_key( depth+1, max_depth, &tmp ) & TRUST_MASK; + if( nt < TRUST_MARGINAL ) { + printf("%*s* ", dbglen, ""); + dbglen += 2; + continue; + } + + if( nt == TRUST_ULTIMATE ) { + /* we have signed this key and only in this special case + * we assume a completes-needed or marginals-needed of 1 */ + printf("%*s", dbglen, ""); + if( ot == TRUST_MARGINAL ) + puts("marginal (1st level)"); + else if( ot == TRUST_FULLY ) + puts("fully (1st level)"); + else + puts("????? (1st level)"); + return ot; + } + + if( nt >= TRUST_FULLY ) + fully++; + if( nt >= TRUST_MARGINAL ) + marginal++; + + if( fully >= opt.completes_needed + || marginal >= opt.marginals_needed ) { + printf("%*s", dbglen, ""); + puts("fully"); + return TRUST_FULLY; } } } - release_lid_table(work); - *ret_tslist = tslist; } - else { /* error: release tslist */ - while( tslist ) { - tsl = tslist->next; - m_free(tslist); - tslist = tsl; - } + printf("%*s", dbglen, ""); + if( marginal ) { + puts("marginal"); + return TRUST_MARGINAL; } - release_lid_table(lids); - return rc; + puts("undefined"); + return TRUST_UNDEFINED; } -/**************** - * Given a trust segment list tslist, walk over all paths and fill in - * the trust information for each segment. What this function does is - * to assign a trustvalue to the first segment (which is the requested key) - * of each path. - * - * FIXME: We have to do more thinking here. e.g. we should never increase - * the trust value. - * - * Do not do it for duplicates. - */ static int -propagate_trust( TRUST_SEG_LIST tslist ) +list_paths( int depth, int max_depth, TRUSTREC *drec ) { - int i; - unsigned trust, tr; - TRUST_SEG_LIST tsl; + ulong rn, uidrn; + int marginal=0; + int fully=0; + size_t dbglen; - for(tsl = tslist; tsl; tsl = tsl->next ) { - if( tsl->dup ) - continue; - assert( tsl->nseg ); - /* the last segment is always an ultimately trusted one, so we can - * assign a fully trust to the next one */ - i = tsl->nseg-1; - tsl->seg[i].trust = TRUST_ULTIMATE; - trust = TRUST_FULLY; - for(i-- ; i >= 0; i-- ) { - tsl->seg[i].trust = trust; - if( i > 0 ) { - /* get the trust of this pubkey */ - tr = get_ownertrust( tsl->seg[i].lid ); - if( tr < trust ) - trust = tr; + if( depth >= max_depth ) { + /* max cert_depth reached */ + puts("undefined (too deep)"); + return TRUST_UNDEFINED; + } + if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) { + /* we are at the end of a path */ + puts("ultimate"); + return TRUST_ULTIMATE; + } + + /* loop over all user-ids */ + for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) { + TRUSTREC rec; /* used for uids and sigs */ + ulong sigrn; + + read_record( rn, &rec, RECTYPE_UID ); + uidrn = rec.r.uid.next; + /* fixme: continue if the uidrec is not marked valid */ + + /* loop over all signature records */ + for( rn = rec.r.uid.siglist; rn; rn = sigrn ) { + int i; + + read_record( rn, &rec, RECTYPE_SIG ); + sigrn = rec.r.sig.next; + + for(i=0; i < SIGS_PER_RECORD; i++ ) { + TRUSTREC tmp; + int ot, nt; + + if( !rec.r.sig.sig[i].lid ) + continue; /* skip deleted sigs */ + if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) + continue; /* skip unchecked signatures */ + if( !(rec.r.sig.sig[i].flag & SIGF_VALID) ) + continue; /* skip invalid signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) ) + continue; /* skip expired signatures */ + if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) ) + continue; /* skip revoked signatures */ + /* fixme: skip duplicates */ + + read_record( rec.r.sig.sig[i].lid, &tmp, RECTYPE_DIR ); + ot = tmp.r.dir.ownertrust & TRUST_MASK; + if( ot < TRUST_MARGINAL ) { + printf(". "); + continue; /* ownertrust is too low; don't need to check */ + } + + if( ot >= TRUST_FULLY ) + ot = TRUST_FULLY; /* just in case */ + + puts(""); + nt = verify_key( depth+1, max_depth, &tmp ) & TRUST_MASK; + if( nt < TRUST_MARGINAL ) { + printf("%*s* ", dbglen, ""); + dbglen += 2; + continue; + } + + if( nt == TRUST_ULTIMATE ) { + /* we have signed this key and only in this special case + * we assume a completes-needed or marginals-needed of 1 */ + printf("%*s", dbglen, ""); + if( ot == TRUST_MARGINAL ) + puts("marginal (1st level)"); + else if( ot == TRUST_FULLY ) + puts("fully (1st level)"); + else + puts("????? (1st level)"); + return ot; + } + + if( nt >= TRUST_FULLY ) + fully++; + if( nt >= TRUST_MARGINAL ) + marginal++; + + if( fully >= opt.completes_needed + || marginal >= opt.marginals_needed ) { + printf("%*s", dbglen, ""); + puts("fully"); + return TRUST_FULLY; + } } } } - return 0; + printf("%*s", dbglen, ""); + if( marginal ) { + puts("marginal"); + return TRUST_MARGINAL; + } + puts("undefined"); + return TRUST_UNDEFINED; } /**************** * we have the pubkey record and all needed informations are in the trustdb * but nothing more is known. - * (this function may re-read the dir record dr) */ static int do_check( TRUSTREC *dr, unsigned *trustlevel ) { - int i, rc=0; - TRUST_SEG_LIST tsl, tsl2, tslist; - int marginal, fully; - int fully_needed = opt.completes_needed; - int marginal_needed = opt.marginals_needed; - unsigned tflags = 0; - - assert( fully_needed > 0 && marginal_needed > 1 ); - - - *trustlevel = TRUST_UNDEFINED; - if( !dr->r.dir.keylist ) { log_error("Ooops, no keys\n"); return G10ERR_TRUSTDB; @@ -881,92 +937,15 @@ do_check( TRUSTREC *dr, unsigned *trustlevel ) return G10ERR_TRUSTDB; } - /* did we already check the signatures */ - /* fixme:.... */ + *trustlevel = verify_key( 1, 5, dr ); if( dr->r.dir.dirflags & DIRF_REVOKED ) - tflags |= TRUST_FLAG_REVOKED; + *trustlevel |= TRUST_FLAG_REVOKED; - #if 0 /* Do we still need this?? */ - if( !rc && !dr->r.dir.siglist ) { - /* We do not have any signatures; check whether it is one of our - * secret keys */ - if( !qry_lid_table_flag( ultikey_table, dr->r.dir.lid, NULL ) ) - *trustlevel = tflags | TRUST_ULTIMATE; - return 0; - } - #endif - if( rc ) - return rc; /* error while looking for sigrec or building sigrecs */ - - /* fixme: take it from the cache if it is valid */ - - /* Make a list of all possible trust-paths */ - rc = make_tsl( dr->r.dir.lid, &tslist ); - if( rc ) - return rc; - rc = propagate_trust( tslist ); - if( rc ) - return rc; - for(tsl = tslist; tsl; tsl = tsl->next ) { - if( tsl->dup ) - continue; - - if( opt.verbose ) { - log_info("trust path:" ); - for(i=0; i < tsl->nseg; i++ ) { - putc(' ',stderr); - print_keyid( stderr, tsl->seg[i].lid ); - putc(':',stderr); - print_trust( stderr, tsl->seg[i].trust ); - } - putc('\n',stderr); - } - } - - /* and see whether there is a trusted path. - * We only have to look at the first segment, because - * propagate_trust has investigated all other segments */ - marginal = fully = 0; - for(tsl = tslist; tsl; tsl = tsl->next ) { - if( tsl->dup ) - continue; - if( tsl->seg[0].trust == TRUST_ULTIMATE ) { - *trustlevel = tflags | TRUST_ULTIMATE; /* our own key */ - break; - } - if( tsl->seg[0].trust == TRUST_FULLY ) { - marginal++; - fully++; - } - else if( tsl->seg[0].trust == TRUST_MARGINAL ) - marginal++; - - if( fully >= fully_needed ) { - *trustlevel = tflags | TRUST_FULLY; - break; - } - } - if( !tsl && marginal >= marginal_needed ) - *trustlevel = tflags | TRUST_MARGINAL; - - /* cache the tslist */ - if( last_trust_web_key ) { - for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) { - tsl2 = tsl->next; - m_free(tsl); - } - } - last_trust_web_key = dr->r.dir.lid; - last_trust_web_tslist = tslist; return 0; } -/*********************************************** - **************** API ************************ - ***********************************************/ - /**************** * Perform some checks over the trustdb * level 0: only open the db @@ -1059,6 +1038,9 @@ export_ownertrust() byte *p; int rc; + printf("# List of assigned trustvalues, created %s\n" + "# (Use \"gpgm --import-ownertrust\" to restore them)\n", + asctimestamp( make_timestamp() ) ); for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) { if( rec.rectype == RECTYPE_DIR ) { if( !rec.r.dir.keylist ) { @@ -1184,7 +1166,6 @@ list_trust_path( int max_depth, const char *username ) { int rc; int wipe=0; - int i; TRUSTREC rec; PKT_public_key *pk = m_alloc_clear( sizeof *pk ); @@ -1192,6 +1173,8 @@ list_trust_path( int max_depth, const char *username ) wipe = 1; max_depth = -max_depth; } + if( max_depth < 1 ) + max_depth = 1; if( (rc = get_pubkey_byname( pk, username )) ) log_error("user '%s' not found: %s\n", username, g10_errstr(rc) ); @@ -1208,61 +1191,6 @@ list_trust_path( int max_depth, const char *username ) } } - if( !rc ) { - TRUST_SEG_LIST tsl, tslist = NULL; - - if( !qry_lid_table_flag( ultikey_table, pk->local_id, NULL ) ) { - tslist = m_alloc( sizeof *tslist ); - tslist->nseg = 1; - tslist->dup = 0; - tslist->seg[0].lid = pk->local_id; - tslist->seg[0].trust = 0; - tslist->next = NULL; - rc = 0; - } - else { - LOCAL_ID_INFO *lids = new_lid_table(); - TRUST_INFO stack[MAX_LIST_SIGS_DEPTH]; - - stack[0].lid = pk->local_id; - stack[0].trust = 0; - rc = do_list_path( stack, 1, max_depth, lids, &tslist ); - if( wipe ) { /* wipe out duplicates */ - LOCAL_ID_INFO *work; - - work = new_lid_table(); - for( tsl=tslist; tsl; tsl = tsl->next ) { - for(i=1; i < tsl->nseg-1; i++ ) { - if( ins_lid_table_item( work, tsl->seg[i].lid, 0 ) ) { - tsl->dup = 1; /* mark as duplicate */ - break; - } - } - } - release_lid_table(work); - } - release_lid_table(lids); - } - if( rc ) - log_error("user '%s' list problem: %s\n", username, g10_errstr(rc)); - rc = propagate_trust( tslist ); - if( rc ) - log_error("user '%s' trust problem: %s\n", username, g10_errstr(rc)); - for(tsl = tslist; tsl; tsl = tsl->next ) { - int i; - - if( tsl->dup ) - continue; - printf("trust path:" ); - for(i=0; i < tsl->nseg; i++ ) { - putc(' ',stdout); - print_keyid( stdout, tsl->seg[i].lid ); - putc(':',stdout); - print_trust( stdout, tsl->seg[i].trust ); - } - putchar('\n'); - } - } free_public_key( pk ); } @@ -1288,7 +1216,9 @@ check_trustdb( const char *username ) username, g10_errstr(rc)); } else { - rc = update_trust_record( keyblock ); + int modified; + + rc = update_trust_record( keyblock, &modified ); if( rc == -1 ) { /* not yet in trustdb: insert */ rc = insert_trust_record( find_kbnode( keyblock, PKT_PUBLIC_KEY @@ -1298,20 +1228,27 @@ check_trustdb( const char *username ) if( rc ) log_error("%s: update failed: %s\n", username, g10_errstr(rc) ); - else + else if( modified ) log_info("%s: updated\n", username ); + else + log_info("%s: okay\n", username ); } release_kbnode( keyblock ); keyblock = NULL; } else { ulong recnum; + ulong count=0, upd_count=0, err_count=0, skip_count=0; for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) { if( rec.rectype == RECTYPE_DIR ) { TRUSTREC tmp; + int modified; + if( !rec.r.dir.keylist ) { log_info("lid %lu: dir record w/o key - skipped\n", recnum); + count++; + skip_count++; continue; } @@ -1323,18 +1260,37 @@ check_trustdb( const char *username ) if( rc ) { log_error("lid %lu: keyblock not found: %s\n", recnum, g10_errstr(rc) ); + count++; + skip_count++; continue; } - rc = update_trust_record( keyblock ); - if( rc ) + + rc = update_trust_record( keyblock, &modified ); + if( rc ) { log_error("lid %lu: update failed: %s\n", recnum, g10_errstr(rc) ); - else - log_info("lid %lu: updated\n", recnum ); + err_count++; + } + else if( modified ) { + if( opt.verbose ) + log_info("lid %lu: updated\n", recnum ); + upd_count++; + } + else if( opt.verbose > 1 ) + log_info("lid %lu: okay\n", recnum ); release_kbnode( keyblock ); keyblock = NULL; + if( !(++count % 100) ) + log_info(_("%lu keys so far processed\n"), count); } } + log_info(_("%lu keys processed\n"), count); + if( skip_count ) + log_info(_("\t%lu keys skipped\n"), skip_count); + if( err_count ) + log_info(_("\t%lu keys with errors\n"), err_count); + if( upd_count ) + log_info(_("\t%lu keys updated\n"), upd_count); } } @@ -1348,31 +1304,57 @@ update_trustdb( ) rc = enum_keyblocks( 0, &kbpos, &keyblock ); if( !rc ) { + ulong count=0, upd_count=0, err_count=0, new_count=0; + while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) { - rc = update_trust_record( keyblock ); + int modified; + + rc = update_trust_record( keyblock, &modified ); if( rc == -1 ) { /* not yet in trustdb: insert */ PKT_public_key *pk = find_kbnode( keyblock, PKT_PUBLIC_KEY ) ->pkt->pkt.public_key; rc = insert_trust_record( pk ); - if( rc && !pk->local_id ) + if( rc && !pk->local_id ) { log_error("lid ?: insert failed: %s\n", g10_errstr(rc) ); - else if( rc ) + err_count++; + } + else if( rc ) { log_error("lid %lu: insert failed: %s\n", pk->local_id, g10_errstr(rc) ); - else - log_info("lid %lu: inserted\n", pk->local_id ); + err_count++; + } + else { + if( opt.verbose ) + log_info("lid %lu: inserted\n", pk->local_id ); + new_count++; + } } - else if( rc ) + else if( rc ) { log_error("lid %lu: update failed: %s\n", lid_from_keyblock(keyblock), g10_errstr(rc) ); - else - log_info("lid %lu: updated\n", - lid_from_keyblock(keyblock) ); + err_count++; + } + else if( modified ) { + if( opt.verbose ) + log_info("lid %lu: updated\n", lid_from_keyblock(keyblock)); + upd_count++; + } + else if( opt.verbose > 1 ) + log_info("lid %lu: okay\n", lid_from_keyblock(keyblock) ); release_kbnode( keyblock ); keyblock = NULL; + if( !(++count % 100) ) + log_info(_("%lu keys so far processed\n"), count); } + log_info(_("%lu keys processed\n"), count); + if( err_count ) + log_info(_("\t%lu keys with errors\n"), err_count); + if( upd_count ) + log_info(_("\t%lu keys updated\n"), upd_count); + if( new_count ) + log_info(_("\t%lu keys inserted\n"), new_count); } if( rc && rc != -1 ) log_error("enum_keyblocks failed: %s\n", g10_errstr(rc)); @@ -1510,54 +1492,8 @@ query_trust_info( PKT_public_key *pk ) int enum_trust_web( void **context, ulong *lid ) { - struct { - TRUST_SEG_LIST tsl; - int index; - } *c = *context; + /* REPLACE THIS with a BETTER ONE */ - if( !c ) { /* make a new context */ - c = m_alloc_clear( sizeof *c ); - *context = c; - if( *lid == last_trust_web_key && last_trust_web_tslist ) - c->tsl = last_trust_web_tslist; - else { - TRUST_SEG_LIST tsl, tsl2, tslist; - int rc; - - rc = make_tsl( *lid, &tslist ); - if( rc ) { - log_error("failed to build the TSL\n"); - return rc; - } - /* cache the tslist, so that we do not need to free it */ - if( last_trust_web_key ) { - for( tsl = last_trust_web_tslist; tsl; tsl = tsl2 ) { - tsl2 = tsl->next; - m_free(tsl); - } - } - last_trust_web_key = *lid; - last_trust_web_tslist = tslist; - c->tsl = last_trust_web_tslist; - } - c->index = 1; - } - - if( !lid ) { /* free the context */ - m_free( c ); - *context = NULL; - return 0; - } - - while( c->tsl ) { - if( !c->tsl->dup && c->index < c->tsl->nseg-1 ) { - *lid = c->tsl->seg[c->index].lid; - c->index++; - return 0; - } - c->index = 1; - c->tsl = c->tsl->next; - } return -1; /* eof */ } @@ -1709,7 +1645,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, TRUSTREC *sigrec, int sigidx, ulong hint_owner ) { KBNODE node; - int rc, state=0; + int rc, state; byte uhash[20]; int is_selfsig; PKT_signature *sigpkt = NULL; @@ -1743,6 +1679,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, /* find the correct signature packet */ + state = 0; for( node=keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_USER_ID ) { PKT_user_id *uidpkt = node->pkt->pkt.user_id; @@ -1757,13 +1694,19 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, sigpkt = node->pkt->pkt.signature; if( sigpkt->keyid[0] == sigkid[0] && sigpkt->keyid[1] == sigkid[1] - && (sigpkt->sig_class&~3) == 0x10 ) + && (sigpkt->sig_class&~3) == 0x10 ) { + state = 2; break; /* found */ + } } } if( !node ) { - log_error(_("lid %lu: user id not found in keyblock\n"), lid ); + log_info(_("lid %lu: user id not found in keyblock\n"), lid ); + return ; + } + if( state != 2 ) { + log_info(_("lid %lu: user id without signature\n"), lid ); return ; } @@ -1776,7 +1719,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, if( !rc ) { /* valid signature */ if( opt.verbose ) log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "good signature (3)\n"), + "Good signature (3)\n"), (ulong)keyid[1], lid, uhash[18], uhash[19], (ulong)sigpkt->keyid[1] ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID; @@ -1789,8 +1732,7 @@ check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash, sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY; } else { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "invalid signature: %s\n"), + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: %s\n"), (ulong)keyid[1], lid, uhash[18], uhash[19], (ulong)sigpkt->keyid[1], g10_errstr(rc) ); sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED; @@ -1893,6 +1835,74 @@ process_hintlist( ulong hintlist, ulong hint_owner ) } +/**************** + * Create or update shadow dir record and return the LID of the record + */ +static ulong +create_shadow_dir( PKT_signature *sig, ulong lid ) +{ + TRUSTREC sdir, hlst, tmphlst; + ulong recno, newlid; + int tmpidx; + int rc; + + /* first see whether we already have such a record */ + rc = tdbio_search_sdir( sig->keyid, sig->pubkey_algo, &sdir ); + if( rc && rc != -1 ) { + log_error("tdbio_search_dir failed: %s\n", g10_errstr(rc)); + die_invalid_db(); + } + if( rc == -1 ) { /* not found: create */ + memset( &sdir, 0, sizeof sdir ); + sdir.recnum = tdbio_new_recnum(); + sdir.rectype= RECTYPE_SDIR; + sdir.r.sdir.lid = sdir.recnum; + sdir.r.sdir.keyid[0] = sig->keyid[0]; + sdir.r.sdir.keyid[1] = sig->keyid[1]; + sdir.r.sdir.pubkey_algo = sig->pubkey_algo; + sdir.r.sdir.hintlist = 0; + write_record( &sdir ); + } + newlid = sdir.recnum; + /* Put the record number into the hintlist. + * (It is easier to use the lid and not the record number of the + * key to save some space (assuming that a signator has + * signed more than one user id - and it is easier to implement.) + */ + tmphlst.recnum = 0; + for( recno=sdir.r.sdir.hintlist; recno; recno = hlst.r.hlst.next) { + int i; + read_record( recno, &hlst, RECTYPE_HLST ); + for( i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { + if( !hlst.r.hlst.rnum[i] ) { + if( !tmphlst.recnum ) { + tmphlst = hlst; + tmpidx = i; + } + } + else if( hlst.r.hlst.rnum[i] == lid ) + return newlid; /* the signature is already in the hintlist */ + } + } + /* not yet in the hint list, write it */ + if( tmphlst.recnum ) { /* we have an empty slot */ + tmphlst.r.hlst.rnum[tmpidx] = lid; + write_record( &tmphlst ); + } + else { /* must append a new hlst record */ + memset( &hlst, 0, sizeof hlst ); + hlst.recnum = tdbio_new_recnum(); + hlst.rectype = RECTYPE_HLST; + hlst.r.hlst.next = sdir.r.sdir.hintlist; + hlst.r.hlst.rnum[0] = lid; + write_record( &hlst ); + sdir.r.sdir.hintlist = hlst.recnum; + write_record( &sdir ); + } + + return newlid; +} + static void upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list ) @@ -1941,7 +1951,7 @@ upd_key_record( PKT_public_key *pk, TRUSTREC *drec, RECNO_LIST *recno_list ) static void upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list, - u32 *keyid, ulong *uidrecno, byte *uidhash ) + u32 *keyid, ulong *uidrecno, byte *uidhash ) { TRUSTREC urec; ulong recno, newrecno; @@ -1981,8 +1991,8 @@ upd_uid_record( PKT_user_id *uid, TRUSTREC *drec, RECNO_LIST *recno_list, static void -upd_pref_record( PKT_signature *sig, TRUSTREC *drec, - u32 *keyid, TRUSTREC *urec, byte *uidhash ) +upd_pref_record( PKT_signature *sig, ulong lid, const u32 *keyid, + TRUSTREC *urec, const byte *uidhash ) { static struct { sigsubpkttype_t subpkttype; @@ -2003,7 +2013,8 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, /* First delete all pref records * This is much simpler than checking whether we have to - * do update the record at all - the record cache may care about it */ + * do update the record at all - the record cache may care about it + * FIXME: We never get correct statistics if we di it like this */ for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) { read_record( recno, &prec, RECTYPE_PREF ); delete_record( recno ); @@ -2027,7 +2038,7 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, } memset( &prec, 0, sizeof prec ); prec.rectype = RECTYPE_PREF; - prec.r.pref.lid = drec->recnum; + prec.r.pref.lid = lid; i = 0; } prec.r.pref.data[i++] = prefs[k].preftype; @@ -2053,6 +2064,248 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, } +/**************** + * update self key signatures (class 0x10..0x13) + */ +static void +upd_self_key_sigs( PKT_signature *sig, TRUSTREC *urec, + ulong lid, const u32 *keyid, const byte *uidhash, + KBNODE keyblock, KBNODE signode) +{ + int rc; + + /* must verify this selfsignature here, so that we can + * build the preference record and validate the uid record + */ + if( !(urec->r.uid.uidflags & UIDF_CHECKED) ) { + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X: Good self-signature\n"), + (ulong)keyid[1], lid, uidhash[18], uidhash[19] ); + upd_pref_record( sig, lid, keyid, urec, uidhash ); + urec->r.uid.uidflags = UIDF_CHECKED | UIDF_VALID; + } + else { + log_info(_("key %08lX, uid %02X%02X: Invalid self-signature: %s\n"), + (ulong)keyid[1], uidhash[18], uidhash[19], g10_errstr(rc) ); + urec->r.uid.uidflags = UIDF_CHECKED; + } + urec->dirty = 1; + } +} + + +/**************** + * update non-self key signatures (class 0x10..0x13) + */ +static void +upd_nonself_key_sigs( PKT_signature *sig, TRUSTREC *urec, + ulong lid, const u32 *keyid, const byte *uidhash, + KBNODE keyblock, KBNODE signode) +{ + /* We simply insert the signature into the sig records but + * avoid duplicate ones. We do not check them here because + * there is a big chance, that we import required public keys + * later. The problem with this is that we must somewhere store + * the information about this signature (we need a record id). + * We do this by using the record type shadow dir, which will + * be converted to a dir record as soon as a new public key is + * inserted into the trustdb. + */ + TRUSTREC rec; + ulong recno; + TRUSTREC delrec; + int delrecidx; + int newflag = 0; + ulong newlid = 0; + PKT_public_key *pk = m_alloc_clear( sizeof *pk ); + ulong pk_lid = 0; + int found_sig = 0; + int found_delrec = 0; + int rc; + + delrec.recnum = 0; + + /* get the LID of the pubkey of the signature under verification */ + rc = get_pubkey( pk, sig->keyid ); + if( !rc ) { + if( pk->local_id ) + pk_lid = pk->local_id; + else { + rc = tdbio_search_dir_bypk( pk, &rec ); + if( !rc ) + pk_lid = rec.recnum; + else if( rc == -1 ) { /* see whether there is a sdir instead */ + u32 akid[2]; + + keyid_from_pk( pk, akid ); + rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec ); + if( !rc ) + pk_lid = rec.recnum; + } + } + } + free_public_key( pk ); pk = NULL; + + /* Loop over all signatures just in case one is not correctly + * marked. If we see the correct signature, set a flag. + * delete duplicate signatures (should not happen but...) */ + for( recno = urec->r.uid.siglist; recno; recno = rec.r.sig.next ) { + int i; + + read_record( recno, &rec, RECTYPE_SIG ); + for(i=0; i < SIGS_PER_RECORD; i++ ) { + TRUSTREC tmp; + if( !rec.r.sig.sig[i].lid ) { + if( !found_delrec && !delrec.recnum ) { + delrec = rec; + delrecidx = i; + found_delrec=1; + } + continue; /* skip deleted sigs */ + } + if( rec.r.sig.sig[i].lid == pk_lid ) { + if( found_sig ) { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "duplicated signature - deleted\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + rec.r.sig.sig[i].lid = 0; + rec.dirty = 1; + continue; + } + found_sig = 1; + } + if( rec.r.sig.sig[i].flag & SIGF_CHECKED ) + continue; /* we already checked this signature */ + if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY ) + continue; /* we do not have the public key */ + + read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); + if( tmp.rectype == RECTYPE_DIR ) { + /* In this case we should now be able to check the signature */ + rc = check_key_signature( keyblock, signode, NULL ); + if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_( + "key %08lX.%lu, uid %02X%02X, sig %08lX: " + "Good signature (1)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; + } + else if( rc == G10ERR_NO_PUBKEY ) { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "weird: no public key\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; + } + else { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX:" + " %s\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1], + g10_errstr(rc)); + rec.r.sig.sig[i].flag = SIGF_CHECKED; + } + rec.dirty = 1; + } + else if( tmp.rectype == RECTYPE_SDIR ) { + /* must check that it is the right one */ + if( tmp.r.sdir.keyid[0] == sig->keyid[0] + && tmp.r.sdir.keyid[1] == sig->keyid[1] + && (!tmp.r.sdir.pubkey_algo + || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) { + log_info(_("key %08lX.%lu, uid %02X%02X: " + "has shadow dir %lu but not yet marked.\n"), + (ulong)keyid[1], lid, + uidhash[18], uidhash[19], tmp.recnum ); + rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; + rec.dirty = 1; + /* fixme: should we verify that the record is + * in the hintlist? - This case here should anyway + * never occur */ + } + } + else { + log_error("sig record %lu[%d] points to wrong record.\n", + rec.r.sig.sig[i].lid, i ); + die_invalid_db(); + } + } + if( found_delrec && delrec.recnum ) { + delrec = rec; + found_delrec = 0; /* we only want the first one */ + } + if( rec.dirty ) { + write_record( &rec ); + rec.dirty = 0; + } + } + + if( found_sig ) + return; + + /* at this point, we have verified, that the signature is not in + * our list of signatures. Add a new record with that signature + * and if the public key is there, check the signature. */ + + if( !pk_lid ) /* we have already seen that there is no pubkey */ + rc = G10ERR_NO_PUBKEY; + else + rc = check_key_signature( keyblock, signode, NULL ); + + if( !rc ) { /* valid signature */ + if( opt.verbose ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "Good signature (2)\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + newlid = pk_lid; /* this is the pk of the signature */ + newflag = SIGF_CHECKED | SIGF_VALID; + } + else if( rc == G10ERR_NO_PUBKEY ) { + if( opt.verbose > 1 ) + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " + "no public key\n"), + (ulong)keyid[1], lid, uidhash[18], + uidhash[19], (ulong)sig->keyid[1] ); + newlid = create_shadow_dir( sig, lid ); + newflag = SIGF_NOPUBKEY; + } + else { + log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: %s\n"), + (ulong)keyid[1], lid, uidhash[18], uidhash[19], + (ulong)sig->keyid[1], g10_errstr(rc)); + newlid = create_shadow_dir( sig, lid ); + newflag = SIGF_CHECKED; + } + + if( delrec.recnum ) { /* we can reuse a deleted slot */ + delrec.r.sig.sig[delrecidx].lid = newlid; + delrec.r.sig.sig[delrecidx].flag= newflag; + write_record( &delrec ); + } + else { /* must insert a new sig record */ + TRUSTREC tmp; + + memset( &tmp, 0, sizeof tmp ); + tmp.recnum = tdbio_new_recnum(); + tmp.rectype = RECTYPE_SIG; + tmp.r.sig.lid = lid; + tmp.r.sig.next = urec->r.uid.siglist; + tmp.r.sig.sig[0].lid = newlid; + tmp.r.sig.sig[0].flag= newflag; + write_record( &tmp ); + urec->r.uid.siglist = tmp.recnum; + urec->dirty = 1; + } +} + + /**************** * Note: A signature made with a secondary key is not considered a @@ -2061,10 +2314,9 @@ upd_pref_record( PKT_signature *sig, TRUSTREC *drec, static void upd_sig_record( PKT_signature *sig, TRUSTREC *drec, u32 *keyid, ulong *uidrecno, byte *uidhash, - KBNODE keyblock, KBNODE signode ) + KBNODE keyblock, KBNODE signode) { TRUSTREC urec; - int rc; ulong lid = drec->recnum; if( !*uidrecno ) { @@ -2086,29 +2338,8 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) { if( (sig->sig_class&~3) == 0x10 ) { - /* must verify this selfsignature here, so that we can - * build the preference record and validate the uid record - */ - if( !(urec.r.uid.uidflags & UIDF_CHECKED) ) { - rc = check_key_signature( keyblock, signode, NULL ); - if( !rc ) { - if( opt.verbose ) - log_info(_( - "key %08lX.%lu, uid %02X%02X: " - "good self-signature\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19] ); - upd_pref_record( sig, drec, keyid, &urec, uidhash ); - urec.r.uid.uidflags = UIDF_CHECKED | UIDF_VALID; - } - else { - log_error("key %08lX, uid %02X%02X: " - "invalid self-signature: %s\n", (ulong)keyid[1], - uidhash[18], uidhash[19], g10_errstr(rc) ); - urec.r.uid.uidflags = UIDF_CHECKED; - } - urec.dirty = 1; - } + upd_self_key_sigs( sig, &urec, lid, keyid, uidhash, + keyblock, signode ); } else if( sig->sig_class == 0x18 ) { /* key binding */ /* get the corresponding key */ @@ -2126,264 +2357,8 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, } } else if( (sig->sig_class&~3) == 0x10 ) { - /* We simply insert the signature into the sig records but - * avoid duplicate ones. We do not check them here because - * there is a big chance, that we import required public keys - * later. The problem with this is that we must somewhere store - * the information about this signature (we need a record id). - * We do this by using the record type shadow dir, which will - * be converted to a dir record as soon as a new public key is - * inserted into the trustdb. - */ - TRUSTREC rec; - ulong recno; - TRUSTREC delrec; - int delrecidx; - int newflag = 0; - ulong newlid = 0; - PKT_public_key *pk = m_alloc_clear( sizeof *pk ); - ulong pk_lid = 0; - int found_sig = 0; - int found_delrec = 0; - - delrec.recnum = 0; - - rc = get_pubkey( pk, sig->keyid ); - if( !rc ) { - if( pk->local_id ) - pk_lid = pk->local_id; - else { - rc = tdbio_search_dir_bypk( pk, &rec ); - if( !rc ) - pk_lid = rec.recnum; - else if( rc == -1 ) { /* see whether there is a sdir instead */ - u32 akid[2]; - - keyid_from_pk( pk, akid ); - rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec ); - if( !rc ) - pk_lid = rec.recnum; - } - } - } - free_public_key( pk ); pk = NULL; - - /* Loop over all signatures just in case one is not correctly - * marked. If we see the correct signature, set a flag. - * delete duplicate signatures (should not happen but...) - */ - for( recno = urec.r.uid.siglist; recno; recno = rec.r.sig.next ) { - int i; - - read_record( recno, &rec, RECTYPE_SIG ); - for(i=0; i < SIGS_PER_RECORD; i++ ) { - TRUSTREC tmp; - if( !rec.r.sig.sig[i].lid ) { - if( !found_delrec && !delrec.recnum ) { - delrec = rec; - delrecidx = i; - found_delrec=1; - } - continue; /* skip deleted sigs */ - } - if( rec.r.sig.sig[i].lid == pk_lid ) { - if( found_sig ) { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "duplicated signature - deleted\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); - rec.r.sig.sig[i].lid = 0; - rec.dirty = 1; - } - else - found_sig = 1; - } - if( rec.r.sig.sig[i].flag & SIGF_CHECKED ) - continue; /* we already checked this signature */ - if( rec.r.sig.sig[i].flag & SIGF_NOPUBKEY ) - continue; /* we do not have the public key */ - - read_record( rec.r.sig.sig[i].lid, &tmp, 0 ); - if( tmp.rectype == RECTYPE_DIR ) { - /* In this case we should now be able to check - * the signature: */ - rc = check_key_signature( keyblock, signode, NULL ); - if( !rc ) { /* valid signature */ - if( opt.verbose ) - log_info(_( - "key %08lX.%lu, uid %02X%02X, sig %08lX: " - "good signature (1)\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); - rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID; - } - else if( rc == G10ERR_NO_PUBKEY ) { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "weird: no public key\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); - rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; - } - else { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "invalid signature: %s\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1], - g10_errstr(rc)); - rec.r.sig.sig[i].flag = SIGF_CHECKED; - } - rec.dirty = 1; - } - else if( tmp.rectype == RECTYPE_SDIR ) { - /* must check that it is the right one */ - if( tmp.r.sdir.keyid[0] == sig->keyid[0] - && tmp.r.sdir.keyid[1] == sig->keyid[1] - && (!tmp.r.sdir.pubkey_algo - || tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) { - log_info(_("key %08lX.%lu, uid %02X%02X: " - "has shadow dir %lu but not yet marked.\n"), - (ulong)keyid[1], lid, - uidhash[18], uidhash[19], tmp.recnum ); - rec.r.sig.sig[i].flag = SIGF_NOPUBKEY; - rec.dirty = 1; - /* fixme: should we verify that the record is - * in the hintlist? - This case here should anyway - * never occur */ - } - } - else { - log_error("sig record %lu[%d] points to wrong record.\n", - rec.r.sig.sig[i].lid, i ); - die_invalid_db(); - } - } - if( found_delrec && delrec.recnum ) { - delrec = rec; - found_delrec = 0; /* we onyl want the first one */ - } - if( rec.dirty ) - write_record( &rec ); - } - - if( found_sig ) - goto leave; - - /* at this point, we have verified, that the signature is not in - * our list of signatures. Add a new record with that signature - * and if the public key is there, check the signature. */ - - if( !pk_lid ) - rc = G10ERR_NO_PUBKEY; - else - rc = check_key_signature( keyblock, signode, NULL ); - - if( !rc ) { /* valid signature */ - if( opt.verbose ) - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "good signature (2)\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); - newlid = pk_lid; /* this is the pk of the signature */ - if( !newlid ) - BUG(); - newflag = SIGF_CHECKED | SIGF_VALID; - } - else if( rc == G10ERR_NO_PUBKEY ) { - if( opt.verbose > 1 ) - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "no public key\n"), - (ulong)keyid[1], lid, uidhash[18], - uidhash[19], (ulong)sig->keyid[1] ); - newflag = SIGF_NOPUBKEY; - } - else { - log_info(_("key %08lX.%lu, uid %02X%02X, sig %08lX: " - "invalid signature: %s\n"), - (ulong)keyid[1], lid, uidhash[18], uidhash[19], - (ulong)sig->keyid[1], g10_errstr(rc)); - newflag = SIGF_CHECKED; - } - - if( !newlid ) { /* create a shadow dir record */ - TRUSTREC sdir, hlst, tmphlst; - int tmpidx; - /* first see whether we already have such a record */ - rc = tdbio_search_sdir( sig->keyid, sig->pubkey_algo, &sdir ); - if( rc && rc != -1 ) { - log_error("tdbio_search_dir failed: %s\n", g10_errstr(rc)); - die_invalid_db(); - } - if( rc == -1 ) { /* not found: create */ - memset( &sdir, 0, sizeof sdir ); - sdir.recnum = tdbio_new_recnum(); - sdir.rectype= RECTYPE_SDIR; - sdir.r.sdir.lid = sdir.recnum; - sdir.r.sdir.keyid[0] = sig->keyid[0]; - sdir.r.sdir.keyid[1] = sig->keyid[1]; - sdir.r.sdir.pubkey_algo = sig->pubkey_algo; - sdir.r.sdir.hintlist = 0; - write_record( &sdir ); - } - newlid = sdir.recnum; - /* Put the record number into the hintlist. - * (It is easier to use the lid and not the record number of the - * key to save some space (assuming that a signator has - * signed more than one user id - and it is easier to implement.) - */ - tmphlst.recnum = 0; - for( recno=sdir.r.sdir.hintlist; recno; recno = hlst.r.hlst.next) { - int i; - read_record( recno, &hlst, RECTYPE_HLST ); - for( i=0; i < ITEMS_PER_HLST_RECORD; i++ ) { - if( !hlst.r.hlst.rnum[i] ) { - if( !tmphlst.recnum ) { - tmphlst = hlst; - tmpidx = i; - } - } - else if( hlst.r.hlst.rnum[i] == lid ) - goto have_hint; - } - } - /* not yet in the hint list, write it */ - if( tmphlst.recnum ) { /* we have an empty slot */ - tmphlst.r.hlst.rnum[tmpidx] = lid; - write_record( &tmphlst ); - } - else { /* must append a new hlst record */ - memset( &hlst, 0, sizeof hlst ); - hlst.recnum = tdbio_new_recnum(); - hlst.rectype = RECTYPE_HLST; - hlst.r.hlst.next = sdir.r.sdir.hintlist; - hlst.r.hlst.rnum[0] = lid; - write_record( &hlst ); - sdir.r.sdir.hintlist = hlst.recnum; - write_record( &sdir ); - } - have_hint: /* "goto considered useful" (don't tell Dijkstra) */ - ; - } - - if( delrec.recnum ) { /* we can reuse a deleted slot */ - delrec.r.sig.sig[delrecidx].lid = newlid; - delrec.r.sig.sig[delrecidx].flag= newflag; - write_record( &delrec ); - } - else { /* must insert a new sig record */ - TRUSTREC tmp; - - memset( &tmp, 0, sizeof tmp ); - tmp.recnum = tdbio_new_recnum(); - tmp.rectype = RECTYPE_SIG; - tmp.r.sig.lid = lid; - tmp.r.sig.next = urec.r.uid.siglist; - tmp.r.sig.sig[0].lid = newlid; - tmp.r.sig.sig[0].flag= newflag; - write_record( &tmp ); - urec.r.uid.siglist = tmp.recnum; - urec.dirty = 1; - } - + upd_nonself_key_sigs( sig, &urec, lid, keyid, uidhash, + keyblock, signode ); } else if( sig->sig_class == 0x18 ) { /* key binding */ log_info(_("key %08lX: bogus key binding by %08lX\n"), @@ -2398,12 +2373,13 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, (ulong)keyid[1], (ulong)sig->keyid[1] ); } else if( sig->sig_class == 0x30 ) { /* cert revocation */ - /* FIXME: a signator wants to revoke his certification signature */ + /* fixme: a signator wants to revoke his certification signature */ } - leave: - if( urec.dirty ) + if( urec.dirty ) { write_record( &urec ); + urec.dirty = 0; + } } @@ -2415,7 +2391,7 @@ upd_sig_record( PKT_signature *sig, TRUSTREC *drec, * key, the check is done by some special code in insert_trust_record(). */ int -update_trust_record( KBNODE keyblock ) +update_trust_record( KBNODE keyblock, int *modified ) { PKT_public_key *primary_pk; KBNODE node; @@ -2432,6 +2408,9 @@ update_trust_record( KBNODE keyblock ) RECNO_LIST recno_list = NULL; /* list of verified records */ /* fixme: replace recno_list by a lookup on node->recno */ + if( modified ) + *modified = 0; + node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); primary_pk = node->pkt->pkt.public_key; rc = get_dir_record( primary_pk, &drec ); @@ -2442,7 +2421,10 @@ update_trust_record( KBNODE keyblock ) keyid_from_pk( primary_pk, keyid ); - /* fixme: start a transaction */ + rc = tdbio_begin_transaction(); + if( rc ) + return rc; + /* now update keys and user ids */ for( node=keyblock; node; node = node->next ) { switch( node->pkt->pkttype ) { @@ -2458,17 +2440,16 @@ update_trust_record( KBNODE keyblock ) drec.dirty = 0; } upd_uid_record( node->pkt->pkt.user_id, &drec, &recno_list, - keyid, &uidrecno, uidhash ); + keyid, &uidrecno, uidhash ); break; case PKT_SIGNATURE: - if( drec.dirty ) { /* upd_sig_recrod may read the drec */ - + if( drec.dirty ) { /* upd_sig_recory may read the drec */ write_record( &drec ); drec.dirty = 0; } - upd_sig_record( node->pkt->pkt.signature, &drec, - keyid, &uidrecno, uidhash, keyblock, node ); + upd_sig_record( node->pkt->pkt.signature, &drec, keyid, + &uidrecno, uidhash, keyblock, node ); break; default: @@ -2531,11 +2512,15 @@ update_trust_record( KBNODE keyblock ) if( rc ) - ; /* fixme: cancel transaction */ - else if( drec.dirty ) { - drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */ - write_record( &drec ); - do_sync(); + rc = tdbio_cancel_transaction(); + else { + if( drec.dirty ) { + drec.r.dir.dirflags &= ~DIRF_CHECKED; /* reset flag */ + write_record( &drec ); + } + if( modified && tdbio_is_dirty() ) + *modified = 0; + rc = tdbio_end_transaction(); } rel_recno_list( &recno_list ); return rc; @@ -2638,7 +2623,7 @@ insert_trust_record( PKT_public_key *pk ) } /* and put all the other stuff into the keydb */ - rc = update_trust_record( keyblock ); + rc = update_trust_record( keyblock, NULL ); if( !rc ) process_hintlist( hintlist, dirrec.r.dir.lid ); diff --git a/g10/trustdb.h b/g10/trustdb.h index 8cdf50ec1..01d3dab55 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -60,7 +60,7 @@ ulong lid_from_keyblock( KBNODE keyblock ); int query_trust_record( PKT_public_key *pk ); int clear_trust_checked_flag( PKT_public_key *pk ); int insert_trust_record( PKT_public_key *pk ); -int update_trust_record( KBNODE keyblock ); +int update_trust_record( KBNODE keyblock, int *modified ); int update_ownertrust( ulong lid, unsigned new_trust ); /*-- pkclist.c --*/ diff --git a/include/util.h b/include/util.h index a79b8ef72..5dd656e72 100644 --- a/include/util.h +++ b/include/util.h @@ -125,6 +125,8 @@ const char *strusage( int level ); /*-- fileutil.c --*/ +char * make_basename(const char *filepath); +char * make_dirname(const char *filepath); char *make_filename( const char *first_part, ... ); int compare_filenames( const char *a, const char *b ); const char *print_fname_stdin( const char *s ); diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 000000000..5ed020dea --- /dev/null +++ b/po/ru.po @@ -0,0 +1,2247 @@ +# I finished the translation without looking at the contrib directory of +# GPG site. Werner enlightened me about two previous translations and I +# dared to look in them to correct my translation of questionable phrases. +# So I'd like to thank: +# Artem Belevich +# Alexey Morozov +# Michael Sobolev , 1998 +# Alexey Vyskubov , 1998 +# QingLong (couldn't send an email to let you know) + +msgid "" +msgstr "" +"POT-Creation-Date: 1998-10-07 14:24+0200\n" +"Content-Type: text/plain; charset=\n" +"Date: 1998-01-26 22:08:36+0100\n" +"From: Gregory Steuck \n" +"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments " +"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n" +"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c " +"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c " +"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c " +"g10/mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c " +"g10/sig-check.c g10/sign.c g10/trustdb.c g10/verify.c\n" + +#: util/secmem.c:77 +msgid "Warning: using insecure memory!\n" +msgstr "" +"Внимание, возможна утечка секретных данных!\n" +"Эту проблему можно решить, установив программу suid(root).\n" +"Обратитесь для этого к администратору Вашей системы.\n" + +#: util/miscutil.c:110 +msgid "yes" +msgstr "да(y)" + +#: util/miscutil.c:111 +msgid "yY" +msgstr "yY" + +#: util/errors.c:54 +msgid "General error" +msgstr "Общая ошибка" + +#: util/errors.c:55 +msgid "Unknown packet type" +msgstr "Неизвестный тип пакета" + +#: util/errors.c:56 +msgid "Unknown version" +msgstr "Неизвестная версия" + +#: util/errors.c:57 +msgid "Unknown pubkey algorithm" +msgstr "Неизвестный алгоритм шифрования с открытым ключом" + +#: util/errors.c:58 +msgid "Unknown digest algorithm" +msgstr "Неизвестный алгоритм генерации дайджеста" + +#: util/errors.c:59 +msgid "Bad public key" +msgstr "Плохой открытый ключ" + +#: util/errors.c:60 +msgid "Bad secret key" +msgstr "Плохой секретный ключ" + +#: util/errors.c:61 +msgid "Bad signature" +msgstr "Плохая подпись" + +#: util/errors.c:62 +msgid "Checksum error" +msgstr "Несовпадение контрольной суммы" + +#: util/errors.c:63 +msgid "Bad passphrase" +msgstr "Неверная \"ключевая фраза\"" + +#: util/errors.c:64 +msgid "Public key not found" +msgstr "Открытый ключ не найден" + +#: util/errors.c:65 +msgid "Unknown cipher algorithm" +msgstr "Неизвестный алгоритм шифрования" + +#: util/errors.c:66 +msgid "Can't open the keyring" +msgstr "Невозможно открыть \"связку ключей\"" + +#: util/errors.c:67 +msgid "Invalid packet" +msgstr "Недопустимый пакет" + +#: util/errors.c:68 +msgid "Invalid armor" +msgstr "Недопустимая ASCII-кодировка" + +#: util/errors.c:69 +msgid "No such user id" +msgstr "Неизвестный идентификатор пользователя" + +#: util/errors.c:70 +msgid "Secret key not available" +msgstr "Секретный ключ не существует" + +#: util/errors.c:71 +msgid "Wrong secret key used" +msgstr "Использован неправильный секретный ключ" + +#: util/errors.c:72 +msgid "Not supported" +msgstr "Не поддерживается" + +#: util/errors.c:73 +msgid "Bad key" +msgstr "Плохой ключ" + +#: util/errors.c:74 +msgid "File read error" +msgstr "Ошибка чтения файла" + +#: util/errors.c:75 +msgid "File write error" +msgstr "Ошибка записи файла" + +#: util/errors.c:76 +msgid "Unknown compress algorithm" +msgstr "Неизвестный алгоритм упаковки" + +#: util/errors.c:77 +msgid "File open error" +msgstr "Ошибка открытия файла" + +#: util/errors.c:78 +msgid "File create error" +msgstr "Ошибка создания файла" + +#: util/errors.c:79 +msgid "Invalid passphrase" +msgstr "Неверная \"ключевая фраза\"" + +#: util/errors.c:80 +msgid "Unimplemented pubkey algorithm" +msgstr "Нереализованный алгоритм шифрования с открытым ключом" + +#: util/errors.c:81 +msgid "Unimplemented cipher algorithm" +msgstr "Нереализованный алгоритм шифрования" + +#: util/errors.c:82 +msgid "Unknown signature class" +msgstr "Подпись неизвестного типа" + +#: util/errors.c:83 +msgid "Trust database error" +msgstr "Ошибка в Trust-DB (база данных доверия)" + +#: util/errors.c:84 +msgid "Bad MPI" +msgstr "" + +#: util/errors.c:85 +msgid "Resource limit" +msgstr "Недостаточно ресурсов" + +#: util/errors.c:86 +msgid "Invalid keyring" +msgstr "Недопустимая \"связка ключей\"" + +#: util/errors.c:87 +msgid "Bad certificate" +msgstr "Плохой сертификат" + +#: util/errors.c:88 +msgid "Malformed user id" +msgstr "Недопустимая форма идентификатора пользователя" + +#: util/errors.c:89 +msgid "File close error" +msgstr "Ошибка закрытия файла" + +#: util/errors.c:90 +msgid "File rename error" +msgstr "Ошибка переименования файла" + +#: util/errors.c:91 +msgid "File delete error" +msgstr "Ошибка удаления файла" + +#: util/errors.c:92 +msgid "Unexpected data" +msgstr "Неожиданные данные" + +#: util/errors.c:93 +msgid "Timestamp conflict" +msgstr "Конфликт временных отпечатков (timestamp)" + +#: util/errors.c:94 +msgid "Unusable pubkey algorithm" +msgstr "Непригодный для использования алгоритм открытого ключа" + +#: util/errors.c:95 +msgid "File exists" +msgstr "Файл существует" + +#: util/errors.c:96 +msgid "Weak key" +msgstr "Слабый ключ" + +#: util/logger.c:177 +#, c-format +msgid "Ohhhh jeeee ... this is a bug (%s:%d:%s)\n" +msgstr "Ой-йо ... ошибка в программе (%s:%d:%s)\n" + +#: util/logger.c:183 +#, c-format +msgid "you found a bug ... (%s:%d)\n" +msgstr "Вы нашли ошибку в программе ... (%s:%d)\n" + +#: cipher/rand-dummy.c:112 +msgid "warning: using insecure random number generator!!\n" +msgstr "Внимание: используется ненадежный генератор случайных чисел!\n" + +#: cipher/rand-dummy.c:113 +msgid "" +"The random number generator is only a kludge to let\n" +"it compile - it is in no way a strong RNG!\n" +"\n" +"DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n" +"\n" +msgstr "" +"Используемый генератор случайных чисел -- только заглушка,\n" +"чтобы скомпилировать программу, никак не надежный ГСЧ!\n" +"\n" +"НЕ ПОЛЬЗУЙТЕСЬ ДАННЫМИ СОЗДАННЫМИ ЭТОЙ ПРОГРАММОЙ!\n" +"\n" + +#: cipher/rand-unix.c:149 +#, c-format +msgid "" +"\n" +"Not enough random bytes available. Please do some other work to give\n" +"the OS a chance to collect more entropy! (Need %d more bytes)\n" +msgstr "" +"\n" +"Недостаточно случайных данных. Пожалуйста, поделайте что-нибудь, чтобы\n" +"ОС могла набрать дополнительные случайные числа! (нужно еще %d байт)\n" + +#: g10/g10.c:147 +msgid "" +"@Commands:\n" +" " +msgstr "" +"@Команды:\n" +" " + +#: g10/g10.c:150 +#, fuzzy +msgid "|[file]|make a signature" +msgstr "|[файл]|создать подпись" + +#: g10/g10.c:151 +#, fuzzy +msgid "|[file]|make a clear text signature" +msgstr "|[файл]|создать текстовую подпись" + +#: g10/g10.c:152 +msgid "make a detached signature" +msgstr "создать отдельную подпись" + +#: g10/g10.c:153 +msgid "encrypt data" +msgstr "зашифровать данные" + +#: g10/g10.c:154 +msgid "encryption only with symmetric cipher" +msgstr "зашифровать симметричным алгоритмом" + +#: g10/g10.c:155 +msgid "store only" +msgstr "только сохранить" + +#: g10/g10.c:156 +msgid "decrypt data (default)" +msgstr "расшифровать данные (по умолчанию)" + +#: g10/g10.c:157 +msgid "verify a signature" +msgstr "проверить подпись" + +#: g10/g10.c:159 +msgid "list keys" +msgstr "список ключей" + +#: g10/g10.c:160 +msgid "list keys and signatures" +msgstr "список ключей и подписей" + +#: g10/g10.c:161 +msgid "check key signatures" +msgstr "проверить подпись на ключе" + +#: g10/g10.c:162 +msgid "list keys and fingerprints" +msgstr "список ключей с их \"отпечатками пальцев\"" + +#: g10/g10.c:163 +msgid "list secret keys" +msgstr "список секретных ключей" + +#: g10/g10.c:165 +msgid "generate a new key pair" +msgstr "сгенерировать новую пару ключей (открытый и секретный)" + +#: g10/g10.c:167 +msgid "remove key from the public keyring" +msgstr "удалить ключ со связки" + +#: g10/g10.c:169 +msgid "sign or edit a key" +msgstr "подписать или редактировать ключ" + +#: g10/g10.c:170 +msgid "generate a revocation certificate" +msgstr "сгенерировать отзывающий сертификат" + +#: g10/g10.c:172 +msgid "export keys" +msgstr "экспортировать ключи" + +#: g10/g10.c:175 +msgid "import/merge keys" +msgstr "импортировать/добавить ключи" + +#: g10/g10.c:176 +msgid "list only the sequence of packets" +msgstr "напечатать только последовательность пакетов" + +#: g10/g10.c:178 +#, fuzzy +msgid "export the ownertrust values" +msgstr "экспортировать параметры доверия\n" + +#: g10/g10.c:179 +#, fuzzy +msgid "import ownertrust values" +msgstr "импортировать параметры доверия\n" + +#: g10/g10.c:180 +msgid "|[NAMES]|check the trust database" +msgstr "|[ИМЕНА]|проверить базу данных доверия" + +#: g10/g10.c:181 +msgid "fix a corrupted trust database" +msgstr "исправить разрушенную базу данных доверия" + +#: g10/g10.c:182 +msgid "De-Armor a file or stdin" +msgstr "Декодировать stdin или файл из ASCII-представления" + +#: g10/g10.c:183 +msgid "En-Armor a file or stdin" +msgstr "Закодировать stdin или файл в ASCII-представление" + +#: g10/g10.c:184 +msgid "|algo [files]|print message digests" +msgstr "|algo [files]|напечатать дайджест сообщения" + +#: g10/g10.c:185 +msgid "print all message digests" +msgstr "напечатать все дайджесты сообщения" + +#: g10/g10.c:192 +msgid "" +"@\n" +"Options:\n" +" " +msgstr "" +"@\n" +"Параметры:\n" +" " + +#: g10/g10.c:194 +msgid "create ascii armored output" +msgstr "вывод в ASCII-представлении" + +#: g10/g10.c:196 +msgid "use this user-id to sign or decrypt" +msgstr "использовать указанный идентификатор пользователя для подписи или расшифровки" + +#: g10/g10.c:197 +msgid "use this user-id for encryption" +msgstr "использовать указанный идентификатор пользователя для шифрования" + +#: g10/g10.c:198 +msgid "|N|set compress level N (0 disables)" +msgstr "|N|установить уровень сжатия (0 - не сжимать)" + +#: g10/g10.c:199 +msgid "use canonical text mode" +msgstr "использовать канонический текстовый режим" + +#: g10/g10.c:201 +msgid "use as output file" +msgstr "использовать в качестве выходного файла" + +#: g10/g10.c:202 +msgid "verbose" +msgstr "многословный" + +#. { oDryRun, "dry-run", 0, N_("do not make any changes") }, +#: g10/g10.c:204 +msgid "batch mode: never ask" +msgstr "пакетный режим: ничего не спрашивать" + +#: g10/g10.c:205 +msgid "assume yes on most questions" +msgstr "отвечать \"да\" на большинство вопросов" + +#: g10/g10.c:206 +msgid "assume no on most questions" +msgstr "отвечать \"нет\" на большинство вопросов" + +#: g10/g10.c:207 +msgid "add this keyring to the list of keyrings" +msgstr "добавить эту связку к списку связок ключей" + +#: g10/g10.c:208 +msgid "add this secret keyring to the list" +msgstr "добавить эту секретную связку к списку связок ключей" + +#: g10/g10.c:209 +msgid "|NAME|use NAME as default secret key" +msgstr "|ИМЯ|использовать ИМЯ в качестве секретного ключа по умолчанию" + +#: g10/g10.c:210 +msgid "read options from file" +msgstr "читать параметры из файла" + +#: g10/g10.c:212 +msgid "set debugging flags" +msgstr "установить отладочные флаги" + +#: g10/g10.c:213 +msgid "enable full debugging" +msgstr "разрешить всю отладку" + +#: g10/g10.c:214 +msgid "|FD|write status info to this FD" +msgstr "|FD| записывать информацию о состоянии в дескриптор (FD)" + +#: g10/g10.c:215 +msgid "do not write comment packets" +msgstr "не писать пакеты с комментариями" + +#: g10/g10.c:216 +msgid "(default is 1)" +msgstr "(по умолчанию 1)" + +#: g10/g10.c:217 +msgid "(default is 3)" +msgstr "(по умолчанию 3)" + +#: g10/g10.c:218 +#, fuzzy +msgid "|FILE|load extension module FILE" +msgstr "|ФАЙЛ|загрузить ФАЙЛ с расширяющими модулями" + +#: g10/g10.c:219 +msgid "emulate the mode described in RFC1991" +msgstr "эмулировать режим описанный в RFC1991" + +#: g10/g10.c:220 +#, fuzzy +msgid "|N|use passphrase mode N" +msgstr "|N|использовать ключевую фразу режима N\n" + +#: g10/g10.c:222 +#, fuzzy +msgid "|NAME|use message digest algorithm NAME for passphrases" +msgstr "|ИМЯ|использовать хэш-алгоритм ИМЯ для ключевых фраз" + +#: g10/g10.c:224 +#, fuzzy +msgid "|NAME|use cipher algorithm NAME for passphrases" +msgstr "|ИМЯ|использовать шифровальный алгоритмом ИМЯ для ключевых фраз" + +#: g10/g10.c:226 +msgid "|NAME|use cipher algorithm NAME" +msgstr "|ИМЯ|использовать шифровальный алгоритмом ИМЯ" + +#: g10/g10.c:227 +msgid "|NAME|use message digest algorithm NAME" +msgstr "|ИМЯ|использовать хэш-алгоритм ИМЯ" + +#: g10/g10.c:228 +msgid "|N|use compress algorithm N" +msgstr "|N|использовать алгоритм сжатия N" + +#: g10/g10.c:229 +msgid "throw keyid field of encrypted packets" +msgstr "выбрасывать поле keyid у зашифрованных пакетов" + +#: g10/g10.c:237 +#, fuzzy +msgid "" +"@\n" +"Examples:\n" +"\n" +" -se -r Bob [file] sign and encrypt for user Bob\n" +" --clearsign [file] make a clear text signature\n" +" --detach-sign [file] make a detached signature\n" +" --list-keys [names] show keys\n" +" --fingerprint [names] show fingerprints\n" +msgstr "" +"@\n" +"Примеры:\n" +"\n" +" -se -r Bob [file] подписать и зашифровать для пользователя Bob\n" +" --clearsign [file] сделать текстовую подпись\n" +" --detach-sign [file] сделать отдельную подпись\n" +" --list-keys [names] показать список ключей\n" +" --fingerprint [names] показать \"отпечатки пальцев\" ключей\n" + +#: g10/g10.c:312 +msgid "Please report bugs to .\n" +msgstr "Пожалуйста, отправляйте сообщения об ошибках по адресу .\n" + +#: g10/g10.c:317 +msgid "Usage: gpgm [options] [files] (-h for help)" +msgstr "Использование: gpgm [параметры] [файлы] (-h для помощи)" + +#: g10/g10.c:319 +msgid "Usage: gpg [options] [files] (-h for help)" +msgstr "Использование: gpg [параметры] [файлы] (-h для помощи)" + +#: g10/g10.c:324 +msgid "" +"Syntax: gpgm [options] [files]\n" +"GNUPG maintenance utility\n" +msgstr "" +"Синтаксис: gpgm [параметры] [файлы]\n" +"Программа сопровождения GNUPG\n" + +#: g10/g10.c:327 +msgid "" +"Syntax: gpg [options] [files]\n" +"sign, check, encrypt or decrypt\n" +"default operation depends on the input data\n" +msgstr "" +"Синтаксис: gpg [параметры] [файлы]\n" +"подписывает, проверяет подписи, шифрует или расшифровывает\n" +"режим работы зависит от входных данных\n" + +#: g10/g10.c:333 +msgid "" +"\n" +"Supported algorithms:\n" +msgstr "" +"\n" +"Поддерживаемые алгоритмы:\n" + +#: g10/g10.c:408 +msgid "usage: gpgm [options] " +msgstr "Использование: gpgm [параметры] " + +#: g10/g10.c:410 +msgid "usage: gpg [options] " +msgstr "Использование: gpg [параметры] " + +#: g10/g10.c:451 +msgid "conflicting commands\n" +msgstr "WidersprЭchliche Kommandos\n" + +#: g10/g10.c:590 +#, c-format +msgid "note: no default option file '%s'\n" +msgstr "замечание: файл параметров по умолчанию '%s' отсутствует\n" + +#: g10/g10.c:594 +#, c-format +msgid "option file '%s': %s\n" +msgstr "файл параметров '%s': %s\n" + +#: g10/g10.c:601 +#, c-format +msgid "reading options from '%s'\n" +msgstr "читаются параметры из '%s'\n" + +#: g10/g10.c:768 g10/g10.c:780 +msgid "selected cipher algorithm is invalid\n" +msgstr "выбран недопустимый алгоритм шифрования\n" + +#: g10/g10.c:774 g10/g10.c:786 +msgid "selected digest algorithm is invalid\n" +msgstr "выбран недопустимый дайджест-алгоритм\n" + +#: g10/g10.c:789 +#, c-format +msgid "compress algorithm must be in range %d..%d\n" +msgstr "алгоритм упаковки может иметь значения от %d до %d\n" + +#: g10/g10.c:791 +msgid "completes-needed must be greater than 0\n" +msgstr "completes-needed должен быть больше 0\n" + +#: g10/g10.c:793 +msgid "marginals-needed must be greater than 1\n" +msgstr "marginals-needed должен быть больше 1\n" + +#: g10/g10.c:796 +msgid "note: simple S2K mode (0) is strongly discouraged\n" +msgstr "замечание: простой S2K режим (0) очень не рекомендуется\n" + +#: g10/g10.c:800 +msgid "invalid S2K mode; must be 0, 1 or 3\n" +msgstr "недопустимый режим S2K: должен быть 0, 1 или 3\n" + +#: g10/g10.c:876 +#, c-format +msgid "failed to initialize the TrustDB: %s\n" +msgstr "Ошибка инициализации базы данных доверия: %s\n" + +#: g10/g10.c:882 +msgid "--store [filename]" +msgstr "--store [имя файла]" + +#: g10/g10.c:890 +msgid "--symmetric [filename]" +msgstr "--symmetric [имя файла]" + +#: g10/g10.c:898 +msgid "--encrypt [filename]" +msgstr "--encrypt [имя файла]" + +#: g10/g10.c:911 +msgid "--sign [filename]" +msgstr "--sign [имя файла]" + +#: g10/g10.c:924 +msgid "--sign --encrypt [filename]" +msgstr "--sign --encrypt [имя файла]" + +#: g10/g10.c:938 +msgid "--clearsign [filename]" +msgstr "--clearsign [имя файла]" + +#: g10/g10.c:950 +msgid "--decrypt [filename]" +msgstr "--decrypt [имя файла]" + +#: g10/g10.c:959 +msgid "--edit-key username" +msgstr "--edit-key имя-пользователя" + +#: g10/g10.c:967 +msgid "--delete-secret-key username" +msgstr "--delete-secret-key имя-пользователя" + +#: g10/g10.c:970 +msgid "--delete-key username" +msgstr "--delete-key имя-пользователя" + +#: g10/encode.c:213 g10/g10.c:993 g10/keylist.c:79 +#, c-format +msgid "can't open %s: %s\n" +msgstr "невозможно открыть файл '%s': %s\n" + +#: g10/g10.c:1004 +msgid "-k[v][v][v][c] [userid] [keyring]" +msgstr "-k[v][v][v][c] [идентификатор пользователя] [связка ключей]" + +#: g10/g10.c:1059 +#, c-format +msgid "dearmoring failed: %s\n" +msgstr "ошибка декодирования: %s\n" + +#: g10/g10.c:1067 +#, c-format +msgid "enarmoring failed: %s\n" +msgstr "ошибка кодирования: %s\n" + +#: g10/g10.c:1128 +#, c-format +msgid "invalid hash algorithm '%s'\n" +msgstr "недопустимый хэш-алгоритм '%s'\n" + +#: g10/g10.c:1204 +msgid "[filename]" +msgstr "[имя файла]" + +#: g10/decrypt.c:59 g10/g10.c:1206 g10/verify.c:66 +#, c-format +msgid "can't open '%s'\n" +msgstr "невозможно открыть файл '%s'\n" + +#: g10/g10.c:1251 +msgid "" +"RSA keys are deprecated; please consider creating a new key and use this key " +"in the future\n" +msgstr "" +"Пользование RSA ключами не рекомендуется, пожалуйста, подумайте о создании\n" +"нового ключа для использования в будущем\n" + +#: g10/armor.c:335 g10/armor.c:375 +msgid "armor header: " +msgstr "" + +#: g10/armor.c:340 +#, fuzzy +msgid "invalid clearsig header\n" +msgstr "недопустимое начало текстовой подписи\n" + +#: g10/armor.c:366 +msgid "invalid armor header: " +msgstr "" + +#: g10/armor.c:440 +#, fuzzy, c-format +msgid "armor: %s\n" +msgstr "Кодировка: %s\n" + +#: g10/armor.c:484 +msgid "invalid dash escaped line: " +msgstr "недопустимая строка начинающаяся с минусов: " + +#: g10/armor.c:553 +msgid "invalid clear text header: " +msgstr "недопустимый текстовый заголовок: " + +#: g10/armor.c:783 +#, fuzzy, c-format +msgid "invalid radix64 character %02x skipped\n" +msgstr "недопустимый для кодировки radix64 символ %02x пропущен\n" + +#: g10/armor.c:816 +msgid "premature eof (no CRC)\n" +msgstr "неожиданный конец файла (нет CRC)\n" + +#: g10/armor.c:835 +msgid "premature eof (in CRC)\n" +msgstr "неожиданный конец файла (в CRC)\n" + +#: g10/armor.c:839 +msgid "malformed CRC\n" +msgstr "неправильная форма CRC\n" + +#: g10/armor.c:843 +#, c-format +msgid "CRC error; %06lx - %06lx\n" +msgstr "ошибка CRC; %06lx - %06lx\n" + +#: g10/armor.c:862 +msgid "premature eof (in Trailer)\n" +msgstr "неожиданный конец файла (в хвосте)\n" + +#: g10/armor.c:866 +msgid "error in trailer line\n" +msgstr "ошибка в завершающей строке\n" + +#: g10/armor.c:1120 +msgid "no valid RFC1991 or OpenPGP data found.\n" +msgstr "не найдено допустимых RFC1991 или OpenPGP данных.\n" + +#: g10/pkclist.c:71 +#, c-format +msgid "" +"No owner trust defined for %lu:\n" +"%4u%c/%08lX %s \"" +msgstr "" +"Не определены параметры доверия для %lu:\n" +"%4u%c/%08lX %s \"" + +#: g10/pkclist.c:81 +#, fuzzy +msgid "" +"Please decide how far you trust this user to correctly\n" +"verify other users' keys (by looking at passports,\n" +"checking fingerprints from different sources...)?\n" +"\n" +" 1 = Don't know\n" +" 2 = I do NOT trust\n" +" 3 = I trust marginally\n" +" 4 = I trust fully\n" +" s = please show me more information\n" +msgstr "" +"\"\n" +"\n" +"Пожалуйста решите, насколько вы доверяете этому пользователю проверять\n" +"чужие ключи (глядя в паспорта, проверяя \"отпечатки пальцев\" по другим\n" +"источникам)?\n" +"\n" +" 1 = Не знаю\n" +" 2 = Нет, не доверяю\n" +" 3 = Верю отчасти\n" +" 4 = Верю полностью\n" +" s = Пожалуйста, покажите дополнительную информацию\n" + +#: g10/pkclist.c:90 +msgid " m = back to the main menu\n" +msgstr " m = обратно в главное меню\n" + +# valid user replies (not including 1..4) +#. a string with valid answers +#: g10/pkclist.c:95 +msgid "sSmM" +msgstr "sSmM" + +#: g10/pkclist.c:99 +msgid "edit_ownertrust.value" +msgstr "" + +#: g10/pkclist.c:99 +msgid "Your decision? " +msgstr "Ваше решение? " + +#: g10/pkclist.c:118 +msgid "You will see a list of signators etc. here\n" +msgstr "Здесь вы увидите список подписавших и т.д.\n" + +#: g10/pkclist.c:145 +msgid "" +"Could not find a valid trust path to the key. Let's see whether we\n" +"can assign some missing owner trust values.\n" +"\n" +msgstr "" +"Не получилось найти цепочку доверия для ключа. Посмотрим, можно ли присвоить\n" +"некоторые недостающие значения \"доверия владельцу\"\n" +"\n" + +#: g10/pkclist.c:168 +msgid "" +"No owner trust values changed.\n" +"\n" +msgstr "Значения параметров доверия не изменены.\n" + +#: g10/pkclist.c:188 +msgid "revoked_key.override" +msgstr "" + +#: g10/pkclist.c:189 g10/pkclist.c:279 +msgid "Use this key anyway? " +msgstr "Все равно использовать этот ключ?" + +#: g10/pkclist.c:274 +msgid "" +"It is NOT certain that the key belongs to its owner.\n" +"If you *really* know what you are doing, you may answer\n" +"the next question with yes\n" +"\n" +msgstr "" +"Невозможно установить достоверно, что ключ принадлежит тому,\n" +"кто указан его владельцем. Отвечайте \"да\" на следующий вопрос,\n" +"только если вы *действительно* понимаете что делаете.\n" + +#: g10/pkclist.c:278 +msgid "untrusted_key.override" +msgstr "" + +#: g10/pkclist.c:283 +msgid "WARNING: Using untrusted key!\n" +msgstr "ВНИМАНИЕ: Используется ключ к которому нет доверия!\n" + +#: g10/pkclist.c:319 +msgid "WARNING: This key has been revoked by its owner!\n" +msgstr "ВНИМАНИЕ: Владелец ключа уже отозвал его!\n" + +#: g10/pkclist.c:320 +msgid " This could mean that the signature is forgery.\n" +msgstr " Это может означать, что подпись поддельная.\n" + +#: g10/pkclist.c:341 +msgid "Note: This key has expired!\n" +msgstr "Замечание: Срок действия ключа уже истек!\n" + +#: g10/pkclist.c:348 +msgid "WARNING: This key is not certified with a trusted signature!\n" +msgstr "ВНИМАНИЕ: Этот ключ не заверен доверенной подписью!\n" + +#: g10/pkclist.c:350 +msgid "" +" There is no indication that the signature belongs to the owner.\n" +msgstr "" +" Нет никаких указания на то, что ключ принадлежит его владельцу.\n" + +#: g10/pkclist.c:365 +msgid "WARNING: We do NOT trust this key!\n" +msgstr "ВНИМАНИЕ: Мы НЕ доверяем этому ключу!\n" + +#: g10/pkclist.c:366 +msgid " The signature is probably a FORGERY.\n" +msgstr " Подпись вероятно -- ПОДДЕЛКА.\n" + +#: g10/pkclist.c:373 +msgid "" +"WARNING: This key is not certified with sufficiently trusted signatures!\n" +msgstr "" +"ВНИМАНИЕ: Этот ключ не заверен достаточно доверенными подписями!\n" + +#: g10/pkclist.c:376 +msgid " It is not certain that the signature belongs to the owner.\n" +msgstr " Нет уверенности, что подпись принадлежит владельцу.\n" + +#: g10/pkclist.c:421 +msgid "" +"You did not specify a user ID. (you may use \"-r\")\n" +"\n" +msgstr "" +"Вы не указали идентификатор пользователя (воспользуйтесь параметром \"-r\").\n" +"\n" + +#: g10/pkclist.c:425 +msgid "pklist.user_id.enter" +msgstr "" + +#: g10/pkclist.c:426 +msgid "Enter the user ID: " +msgstr "Введите идентификатор пользователя: " + +#: g10/pkclist.c:437 +msgid "No such user ID.\n" +msgstr "Нет такого идентификатора пользователя.\n" + +#: g10/pkclist.c:471 g10/pkclist.c:498 +#, c-format +msgid "%s: skipped: %s\n" +msgstr "%s: пропущен: %s\n" + +#: g10/pkclist.c:479 +#, c-format +msgid "%s: error checking key: %s\n" +msgstr "%s: ошибка при проверке ключа: %s\n" + +#: g10/pkclist.c:505 +msgid "no valid addressees\n" +msgstr "нет допустимых адресов\n" + +#: g10/keygen.c:123 +msgid "writing self signature\n" +msgstr "пишется само-подпись\n" + +#: g10/keygen.c:161 +msgid "writing key binding signature\n" +msgstr "пишется \"key-binding\" подпись\n" + +#: g10/keygen.c:383 +msgid "Please select what kind of key you want:\n" +msgstr "Выберите желаемый тип ключа:\n" + +#: g10/keygen.c:385 +#, c-format +msgid " (%d) DSA and ElGamal (default)\n" +msgstr " (%d) DSA и ElGamal (по умолчанию)\n" + +#: g10/keygen.c:386 +#, c-format +msgid " (%d) ElGamal (sign and encrypt)\n" +msgstr " (%d) ElGamal (подпись и шифрование)\n" + +#: g10/keygen.c:388 +#, c-format +msgid " (%d) ElGamal (encrypt only)\n" +msgstr " (%d) ElGamal (только шифрование)\n" + +#: g10/keygen.c:389 +#, c-format +msgid " (%d) DSA (sign only)\n" +msgstr " (%d) DSA (только подпись)\n" + +#: g10/keygen.c:390 +#, c-format +msgid " (%d) ElGamal in a v3 packet\n" +msgstr " (%d) ElGamal в v3-пакете\n" + +#: g10/keygen.c:394 +msgid "keygen.algo" +msgstr "" + +#: g10/keygen.c:394 +msgid "Your selection? " +msgstr "Ваш выбор? " + +#: g10/keygen.c:420 +msgid "Invalid selection.\n" +msgstr "Недопустимый выбор.\n" + +#: g10/keygen.c:432 +#, c-format +msgid "" +"About to generate a new %s keypair.\n" +" minimum keysize is 768 bits\n" +" default keysize is 1024 bits\n" +" highest suggested keysize is 2048 bits\n" +msgstr "" +"Собираемся сгенерировать %s ключевую пару.\n" +" минимальная длина ключа: 768 бит\n" +" длина ключа по умолчанию: 1024 бита\n" +" максимальная рекомендуемая длина ключа: 2048 бит\n" + +#: g10/keygen.c:438 +msgid "keygen.size" +msgstr "" + +#: g10/keygen.c:439 +msgid "What keysize do you want? (1024) " +msgstr "Какого размера ключ вы желаете? (1024)" + +#: g10/keygen.c:444 +msgid "DSA only allows keysizes from 512 to 1024\n" +msgstr "Допустимый размер DSA ключей - от 512 до 1024 бит\n" + +#: g10/keygen.c:446 +msgid "keysize too small; 768 is smallest value allowed.\n" +msgstr "слишком маленькая длина ключа, наименьшее значение - 768.\n" + +#: g10/keygen.c:449 +#, fuzzy +msgid "" +"Keysizes larger than 2048 are not suggested because\n" +"computations take REALLY long!\n" +msgstr "" +"Ключи длиной больше 2048 не рекомендуются, потому что вычисления" +"занимают ОЧЕНЬ много времени!\n" + +#: g10/keygen.c:451 +msgid "keygen.size.huge.okay" +msgstr "" + +#: g10/keygen.c:452 +msgid "Are you sure that you want this keysize? " +msgstr "Вы действительно хотите ключ такой длины? " + +#: g10/keygen.c:453 +msgid "" +"Okay, but keep in mind that your monitor and keyboard radiation is also very " +"vulnerable to attacks!\n" +msgstr "" +"Ок, только не забывайте, что излучение ваших клавиатуры и монитора тоже\n" +"делают вас уязвимым для атак.\n" + +#: g10/keygen.c:460 +msgid "keygen.size.large.okay" +msgstr "" + +#: g10/keygen.c:461 +msgid "Do you really need such a large keysize? " +msgstr "Вам действительно нужен такой длинный ключ? " + +#: g10/keygen.c:467 +#, c-format +msgid "Requested keysize is %u bits\n" +msgstr "Запрошенный ключ имеет длину %u бит\n" + +#: g10/keygen.c:470 g10/keygen.c:474 +#, c-format +msgid "rounded up to %u bits\n" +msgstr "округлено до %u бит\n" + +#: g10/keygen.c:486 +msgid "" +"Please specify how long the key should be valid.\n" +" 0 = key does not expire\n" +" = key expires in n days\n" +" w = key expires in n weeks\n" +" m = key expires in n months\n" +" y = key expires in n years\n" +msgstr "" +"Пожалуйста, укажите продолжительность действия вашего ключа.\n" +" 0 = бессрочный ключ\n" +" = срок действия ключа n дней\n" +" w = срок действия ключа n недель\n" +" m = срок действия ключа n месяцев\n" +" y = срок действия ключа n лет\n" + +#: g10/keygen.c:501 +msgid "keygen.valid" +msgstr "" + +#: g10/keygen.c:501 +msgid "Key is valid for? (0) " +msgstr "Ключ действителен в течение? (0) " + +#: g10/keygen.c:512 +msgid "invalid value\n" +msgstr "недопустимое значение.\n" + +#: g10/keygen.c:517 +msgid "Key does not expire at all\n" +msgstr "Бессрочный ключ.\n" + +#. print the date when the key expires +#: g10/keygen.c:520 +#, c-format +msgid "Key expires at %s\n" +msgstr "Ключ действует до %s\n" + +#: g10/keygen.c:525 +msgid "keygen.valid.okay" +msgstr "" + +#: g10/keygen.c:526 +msgid "Is this correct (y/n)? " +msgstr "Это верно? (y/n) " + +#: g10/keygen.c:554 +msgid "" +"\n" +"You need a User-ID to identify your key; the software constructs the user " +"id\n" +"from Real Name, Comment and Email Address in this form:\n" +" \"Heinrich Heine (Der Dichter) \"\n" +"\n" +msgstr "" +"\n" +"Для идентификации ключа необходим идентификатор пользователя; программа\n" +"конструирует его из полного имени пользователя, комментария и адреса email" +"в виде:\n" +" \"Vasya Pupkin (KRUTOI) \"\n" +"\n" + +#: g10/keygen.c:565 +msgid "keygen.name" +msgstr "" + +#: g10/keygen.c:565 +msgid "Real name: " +msgstr "Ваше имя (\"Имя Фамилия\"): " + +#: g10/keygen.c:569 +msgid "Invalid character in name\n" +msgstr "Недопустимый символ в имени\n" + +#: g10/keygen.c:571 +msgid "Name may not start with a digit\n" +msgstr "Полное имя не может начинаться с цифры.\n" + +#: g10/keygen.c:573 +msgid "Name must be at least 5 characters long\n" +msgstr "Полное имя должно состоять не менее чем из 5ти символов.\n" + +#: g10/keygen.c:581 +msgid "keygen.email" +msgstr "" + +#: g10/keygen.c:581 +msgid "Email address: " +msgstr "E-Mail: " + +#: g10/keygen.c:593 +msgid "Not a valid email address\n" +msgstr "Недопустимый E-Mail\n" + +#: g10/keygen.c:601 +msgid "keygen.comment" +msgstr "" + +#: g10/keygen.c:601 +msgid "Comment: " +msgstr "Комментарий: " + +#: g10/keygen.c:607 +msgid "Invalid character in comment\n" +msgstr "Недопустимый символ в комментарии.\n" + +#: g10/keygen.c:627 +#, c-format +msgid "" +"You selected this USER-ID:\n" +" \"%s\"\n" +"\n" +msgstr "" +"Вы выбрали идентификатор пользователя:\n" +" \"%s\"\n" +"\n" + +#: g10/keygen.c:630 +msgid "NnCcEeOoQq" +msgstr "" + +#: g10/keygen.c:639 +#, fuzzy +msgid "keygen.userid.cmd" +msgstr "" + +#: g10/keygen.c:640 +#, fuzzy +msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? " +msgstr "Изменить: N=Имя, C=Комментарий, E=E-Mail, O=Okay/Q=Выход? " + +#: g10/keygen.c:687 +msgid "" +"You need a Passphrase to protect your secret key.\n" +"\n" +msgstr "" +"Для защиты вашего ключа нужна ключевая фраза.\n" +"\n" + +#: g10/keyedit.c:388 g10/keygen.c:695 +msgid "passphrase not correctly repeated; try again.\n" +msgstr "ключевая фраза не была воспроизведена, попробуйте снова.\n" + +#: g10/keygen.c:701 +msgid "" +"You don't want a passphrase - this is probably a *bad* idea!\n" +"I will do it anyway. You can change your passphrase at any time,\n" +"using this program with the option \"--edit-key\".\n" +"\n" +msgstr "" +"Вы не хотите использовать ключевую фразу - это, скорее всего, *плохая*\n" +"идея. Но я сделаю, что Вы хотите. Ключевую фразу можно сменить в любое\n" +"время, запустив эту программу с параметром \"--edit-key\".\n" +"\n" + +#: g10/keygen.c:722 +msgid "" +"We need to generate a lot of random bytes. It is a good idea to perform\n" +"some other action (work in another window, move the mouse, utilize the\n" +"network and the disks) during the prime generation; this gives the random\n" +"number generator a better chance to gain enough entropy.\n" +msgstr "" +"Нам нужно сгенерировать много случайных байтов. Сейчас очень хорошо было бы\n" +"что-то поделать на машине (поработать в другом окне, подвигать мышь,\n" +"нагрузить сетевую или дисковую подсистему). Это даст генератору случайных\n" +"чисел возможность набрать достаточно энтропии.\n" + +#: g10/keygen.c:789 +msgid "Key generation can only be used in interactive mode\n" +msgstr "" +"Генерация ключа может быть выполнена только в интерактивном режиме.\n" + +#: g10/keygen.c:797 +msgid "DSA keypair will have 1024 bits.\n" +msgstr "Ключевая пара DSA будет иметь длину 1024 бита.\n" + +#: g10/keygen.c:803 +#, fuzzy +msgid "Key generation cancelled.\n" +msgstr "Генерация ключа отменена: %s\n" + +#: g10/keygen.c:813 +#, c-format +msgid "writing public certificate to '%s'\n" +msgstr "открытый сертификат записывается в '%s'\n" + +#: g10/keygen.c:814 +#, c-format +msgid "writing secret certificate to '%s'\n" +msgstr "секретный сертификат записывается в '%s'\n" + +#: g10/keygen.c:891 +msgid "public and secret key created and signed.\n" +msgstr "открытый и секретный ключи созданы и подписаны.\n" + +#: g10/keygen.c:893 +msgid "" +"Note that this key cannot be used for encryption. You may want to use\n" +"the command \"--add-key\" to generate a secondary key for this purpose.\n" +msgstr "" +"Обратите внимание, что этот ключ не может быть использован для шифрования.\n" +"Вы можете воспользоваться параметром --add-key для генерации дополнительного\n" +"ключа для шифрования.\n" + +#: g10/keygen.c:907 g10/keygen.c:991 +#, c-format +msgid "Key generation failed: %s\n" +msgstr "Генерация ключа не удалась: %s\n" + +#: g10/keygen.c:968 +msgid "keygen.sub.okay" +msgstr "" + +#: g10/keygen.c:969 +#, fuzzy +msgid "Really create? " +msgstr "Действительно создать? " + +#: g10/encode.c:88 +#, c-format +msgid "%s: can't open: %s\n" +msgstr "%s: невозможно открыть: %s\n" + +#: g10/encode.c:107 +#, c-format +msgid "error creating passphrase: %s\n" +msgstr "ошибка при создании ключевой фразы: %s\n" + +#: g10/encode.c:152 g10/encode.c:264 +#, c-format +msgid "%s: warning: empty file\n" +msgstr "%s: предупреждение: пустой файл.\n" + +#: g10/encode.c:219 +#, c-format +msgid "reading from '%s'\n" +msgstr "Читается из '%s'\n" + +#: g10/encode.c:392 +#, c-format +msgid "%s encrypted for: %s\n" +msgstr "%s зашифровано для: %s\n" + +#: g10/getkey.c:884 +#, c-format +msgid "using secondary key %08lX instead of primary key %08lX\n" +msgstr "используется дополнительный ключ %09lX вместо основного %08lX%\n" + +#: g10/import.c:105 g10/trustdb.c:1389 +#, c-format +msgid "can't open file: %s\n" +msgstr "невозможно открыть файл: %s\n" + +#: g10/import.c:121 +#, c-format +msgid "skipping block of type %d\n" +msgstr "пропускаем блок типа %d\n" + +#: g10/import.c:131 g10/trustdb.c:1464 +#, c-format +msgid "read error: %s\n" +msgstr "ошибка чтения: %s\n" + +#: g10/import.c:272 g10/import.c:445 +#, c-format +msgid "key %08lX: no user id\n" +msgstr "ключ %08lX: нет идентификатора пользователя\n" + +#: g10/import.c:282 +#, c-format +msgid "key %08lX: no valid user ids\n" +msgstr "ключ %08lX: нет допустимых идентификаторов пользователей\n" + +#: g10/import.c:284 +msgid "this may be caused by a missing self-signature\n" +msgstr "это может быть вызвано отсутствием само-подписи\n" + +#: g10/import.c:293 g10/import.c:511 +#, c-format +msgid "key %08lX: public key not found: %s\n" +msgstr "ключ %08lX: открытый ключ не найден: %s\n" + +#: g10/import.c:299 +msgid "no default public keyring\n" +msgstr "нет связки открытых ключей по умолчанию\n" + +#: g10/import.c:303 +#, c-format +msgid "writing to '%s'\n" +msgstr "записывается в '%s'\n" + +#: g10/import.c:307 g10/import.c:362 g10/import.c:565 +#, c-format +msgid "can't lock public keyring: %s\n" +msgstr "невозможно заблокировать связку открытых ключей: %s\n" + +#: g10/import.c:310 +#, c-format +msgid "can't write to keyring: %s\n" +msgstr "невозможно записать в связку ключей: %s\n" + +#. we are ready +#: g10/import.c:313 +#, c-format +msgid "key %08lX: public key imported\n" +msgstr "ключ %08lX: открытый ключ импортирован\n" + +#: g10/import.c:322 +#, c-format +msgid "key %08lX: doesn't match our copy\n" +msgstr "ключ %08lX: не совпадает с нашей копией\n" + +#: g10/import.c:335 g10/import.c:520 +#, c-format +msgid "key %08lX: can't locate original keyblock: %s\n" +msgstr "ключ %08lX: невозможно обнаружить original keyblock: %s\n" + +#: g10/import.c:342 g10/import.c:527 +#, c-format +msgid "key %08lX: can't read original keyblock: %s\n" +msgstr "ключ %08lX: невозможно прочитать original keyblock: %s\n" + +#: g10/import.c:359 g10/import.c:460 g10/import.c:562 +msgid "writing keyblock\n" +msgstr "записывается блок ключа\n" + +#: g10/import.c:365 g10/import.c:568 +#, c-format +msgid "can't write keyblock: %s\n" +msgstr "невозможно записать блок ключа: %s\n" + +#: g10/import.c:369 +#, c-format +msgid "key %08lX: 1 new user-id\n" +msgstr "ключ %08lX: 1 новый идентификатор пользователя\n" + +#: g10/import.c:372 +#, c-format +msgid "key %08lX: %d new user-ids\n" +msgstr "ключ %08lX: %d новых идентификаторов пользователей\n" + +#: g10/import.c:375 +#, c-format +msgid "key %08lX: 1 new signature\n" +msgstr "ключ %08lX: 1 новая подпись\n" + +#: g10/import.c:378 +#, c-format +msgid "key %08lX: %d new signatures\n" +msgstr "ключ %08lX: %d новых подписей\n" + +#: g10/import.c:381 +#, c-format +msgid "key %08lX: 1 new subkey\n" +msgstr "ключ %08lX: 1 новый под-ключ\n" + +#: g10/import.c:384 +#, c-format +msgid "key %08lX: %d new subkeys\n" +msgstr "ключ %08lX: %d новых под-ключей\n" + +#: g10/import.c:388 +#, c-format +msgid "key %08lX: not changed\n" +msgstr "ключ %08lX: не изменен\n" + +#: g10/import.c:463 +#, c-format +msgid "can't lock secret keyring: %s\n" +msgstr "невозможно заблокировать связку секретных ключей: %s\n" + +#: g10/import.c:466 +#, fuzzy, c-format +msgid "can't write keyring: %s\n" +msgstr "невозможно записать связку ключей: %s\n" + +#. we are ready +#: g10/import.c:469 +#, c-format +msgid "key %08lX: secret key imported\n" +msgstr "ключ %08lX: секретный ключ импортирован\n" + +#. we can't merge secret keys +#: g10/import.c:472 +#, c-format +msgid "key %08lX: already in secret keyring\n" +msgstr "ключ %08lX: уже на связке секретных ключей\n" + +#: g10/import.c:476 +#, c-format +msgid "key %08lX: secret key not found: %s\n" +msgstr "ключ %08lX: секретный ключ не найден: %s\n" + +#: g10/import.c:505 +#, c-format +msgid "key %08lX: no public key - can't apply revocation certificate\n" +msgstr "" +"ключ %08lX: нет открытого ключа - невозможно применить отзывающий сертификат\n" + +#: g10/import.c:538 +#, c-format +msgid "key %08lX: invalid revocation certificate: %s - rejected\n" +msgstr "ключ %08lX: недопустимый отзывающий сертификат: %s - отвергнут\n" + +#. we are ready +#: g10/import.c:571 +#, c-format +msgid "key %08lX: revocation certificate imported\n" +msgstr "ключ %08lX: отзывающий сертификат импортирован\n" + +#: g10/import.c:601 +#, c-format +msgid "key %08lX: no user-id for signature\n" +msgstr "ключ %08lX: нет идентификатора пользователя для подписи\n" + +#: g10/import.c:608 +#, c-format +msgid "key %08lX: unsupported public key algorithm\n" +msgstr "ключ %08lX: неподдерживаемый алгоритм открытого ключа\n" + +#: g10/import.c:609 +#, c-format +msgid "key %08lX: invalid self-signature\n" +msgstr "ключ %08lX: недопустимая само-подпись\n" + +#: g10/import.c:638 +#, c-format +msgid "key %08lX: skipped userid '" +msgstr "ключ %08lX: пропущен идентификатор пользователя '" + +#: g10/import.c:661 +#, c-format +msgid "key %08lX: revocation certificate at wrong place - skipped\n" +msgstr "ключ %08lX: отзывающий сертификат в неправильном месте - пропущен\n" + +#: g10/import.c:669 +#, c-format +msgid "key %08lX: invalid revocation certificate: %s - skipped\n" +msgstr "ключ %08lX: недопустимый отзывающий сертификат: %s - пропущен\n" + +#: g10/import.c:731 +#, c-format +msgid "key %08lX: revocation certificate added\n" +msgstr "ключ %08lX: отзывающий сертификат добавлен\n" + +#: g10/import.c:794 g10/import.c:830 +#, c-format +msgid "key %08lX: our copy has no self-signature\n" +msgstr "ключ %08lX: наша копия не имеет само-подписи\n" + +#: g10/keyedit.c:80 +#, c-format +msgid "%s: user not found\n" +msgstr "%s: пользователь не найден\n" + +#: g10/keyedit.c:163 +#, fuzzy +msgid "[self-signature]" +msgstr "[само-подпись]\n" + +#: g10/keyedit.c:181 +#, fuzzy +msgid "1 bad signature\n" +msgstr "1 плохая подпись\n" + +#: g10/keyedit.c:183 +#, c-format +msgid "%d bad signatures\n" +msgstr "%d плохих подписей\n" + +#: g10/keyedit.c:185 +#, fuzzy +msgid "1 signature not checked due to a missing key\n" +msgstr "1 подпись не проверена из-за отсутствия ключа\n" + +#: g10/keyedit.c:187 +#, fuzzy, c-format +msgid "%d signatures not checked due to missing keys\n" +msgstr "%s подписей не проверено из-за отсутствия ключей\n" + +#: g10/keyedit.c:189 +#, fuzzy +msgid "1 signature not checked due to an error\n" +msgstr "1 подпись не проверена из-за ошибки\n" + +#: g10/keyedit.c:191 +#, c-format +msgid "%d signatures not checked due to errors\n" +msgstr "%s подписей не проверено из-за ошибок\n" + +#: g10/keyedit.c:193 +#, fuzzy +msgid "1 user id without valid self-signature detected\n" +msgstr "обнаружен 1 идентификатор пользователя без допустимой само-подписи\n" + +#: g10/keyedit.c:195 +#, c-format +msgid "%d user ids without valid self-signatures detected\n" +msgstr "обнаружено %d идентификаторов пользователей без допустимых само-подписей\n" + +#: g10/keyedit.c:257 +#, fuzzy, c-format +msgid "Already signed by key %08lX\n" +msgstr "Уже подписано ключом %08lX.\n" + +#: g10/keyedit.c:265 +#, fuzzy, c-format +msgid "Nothing to sign with key %08lX\n" +msgstr "Нечего подписывать ключам %08lX\n" + +#: g10/keyedit.c:274 +#, fuzzy +msgid "" +"Are you really sure that you want to sign this key\n" +"with your key: \"" +msgstr "Вы действительно уверены, что хотите подписать этот ключ своим:\n" + +#: g10/keyedit.c:281 +msgid "sign_uid.okay" +msgstr "" + +#: g10/keyedit.c:281 +msgid "Really sign? " +msgstr "Действительно подписать? " + +#: g10/keyedit.c:302 +#, fuzzy, c-format +msgid "signing failed: %s\n" +msgstr "ошибка подписывания: %s\n" + +#: g10/keyedit.c:355 +msgid "This key is not protected.\n" +msgstr "Этот ключ не защищен.\n" + +#: g10/keyedit.c:358 +msgid "Key is protected.\n" +msgstr "Этот ключ защищен.\n" + +#: g10/keyedit.c:375 +#, c-format +msgid "Can't edit this key: %s\n" +msgstr "Невозможно редактировать этот ключ: %s\n" + +#: g10/keyedit.c:380 +msgid "" +"Enter the new passphrase for this secret key.\n" +"\n" +msgstr "" +"Введите новую ключевую фразу для этого секретного ключа.\n" +"\n" + +#: g10/keyedit.c:392 +msgid "" +"You don't want a passphrase - this is probably a *bad* idea!\n" +"\n" +msgstr "" +"Вы не хотите ключевую фразу - это скорее всего *плохая* идея!\n" +"\n" + +#: g10/keyedit.c:394 +msgid "change_passwd.empty.okay" +msgstr "" + +#: g10/keyedit.c:395 +msgid "Do you really want to do this? " +msgstr "Вы действительно этого хотите? " + +#: g10/keyedit.c:450 +msgid "quit" +msgstr "выход" + +#: g10/keyedit.c:450 +msgid "quit this menu" +msgstr "выйти из меню" + +#: g10/keyedit.c:451 +msgid "q" +msgstr "" + +#: g10/keyedit.c:452 +msgid "save" +msgstr "записать" + +#: g10/keyedit.c:452 +msgid "save and quit" +msgstr "записать и выйти" + +#: g10/keyedit.c:453 +msgid "help" +msgstr "помощь" + +#: g10/keyedit.c:453 +msgid "show this help" +msgstr "показать помощь" + +#: g10/keyedit.c:455 +msgid "fpr" +msgstr "" + +#: g10/keyedit.c:455 +#, fuzzy +msgid "show fingerprint" +msgstr "показать \"отпечаток пальца\"" + +#: g10/keyedit.c:456 +#, fuzzy +msgid "list" +msgstr "список" + +#: g10/keyedit.c:456 +#, fuzzy +msgid "list key and user ids" +msgstr "список ключей и идентификаторов пользователей" + +#: g10/keyedit.c:457 +msgid "l" +msgstr "" + +#: g10/keyedit.c:458 +msgid "uid" +msgstr "" + +#: g10/keyedit.c:458 +msgid "select user id N" +msgstr "выбрать идентификатор пользователя N" + +#: g10/keyedit.c:459 +msgid "key" +msgstr "ключ" + +#: g10/keyedit.c:459 +msgid "select secondary key N" +msgstr "выбрать дополнительный ключ N" + +#: g10/keyedit.c:460 +msgid "check" +msgstr "проверка" + +#: g10/keyedit.c:460 +#, fuzzy +msgid "list signatures" +msgstr "список ключей и их подписей" + +#: g10/keyedit.c:461 +msgid "c" +msgstr "" + +#: g10/keyedit.c:462 +msgid "sign" +msgstr "подписать" + +#: g10/keyedit.c:462 +#, fuzzy +msgid "sign the key" +msgstr "подписать ключ" + +#: g10/keyedit.c:463 +msgid "s" +msgstr "" + +#: g10/keyedit.c:464 +msgid "debug" +msgstr "отладка" + +#: g10/keyedit.c:465 +msgid "adduid" +msgstr "" + +#: g10/keyedit.c:465 +msgid "add a user id" +msgstr "добавить идентификатор пользователя" + +#: g10/keyedit.c:466 +msgid "deluid" +msgstr "" + +#: g10/keyedit.c:466 +#, fuzzy +msgid "delete user id" +msgstr "удалить идентификатор пользователя" + +#: g10/keyedit.c:467 +msgid "addkey" +msgstr "" + +#: g10/keyedit.c:467 +#, fuzzy +msgid "add a secondary key" +msgstr "добавить дополнительный ключ" + +#: g10/keyedit.c:468 +msgid "delkey" +msgstr "" + +#: g10/keyedit.c:468 +msgid "delete a secondary key" +msgstr "удалить дополнительный ключ" + +#: g10/keyedit.c:469 +msgid "toggle" +msgstr "" + +#: g10/keyedit.c:469 +msgid "toggle between secret and public key listing" +msgstr "переключить между списком секретных и открытых ключей" + +#: g10/keyedit.c:471 +msgid "t" +msgstr "" + +#: g10/keyedit.c:472 +msgid "pref" +msgstr "" + +#: g10/keyedit.c:472 +#, fuzzy +msgid "list preferences" +msgstr "" + +#: g10/keyedit.c:473 +msgid "passwd" +msgstr "" + +#: g10/keyedit.c:473 +#, fuzzy +msgid "change the passphrase" +msgstr "изменить ключевую фразу" + +#: g10/keyedit.c:474 +msgid "trust" +msgstr "" + +#: g10/keyedit.c:474 +msgid "change the ownertrust" +msgstr "изменить параметры доверия" + +#: g10/keyedit.c:492 +msgid "can't do that in batchmode\n" +msgstr "невозможно сделать это в пакетном режиме.\n" + +#. check that they match +#. FIXME: check that they both match +#: g10/keyedit.c:515 +#, fuzzy +msgid "Secret key is available.\n" +msgstr "Имеется секретный ключ.\n" + +#: g10/keyedit.c:531 +msgid "keyedit.cmd" +msgstr "" + +#: g10/keyedit.c:531 +#, fuzzy +msgid "Command> " +msgstr "Команда> " + +#: g10/keyedit.c:556 +#, fuzzy +msgid "Need the secret key to to this.\n" +msgstr "Чтобы это сделать, нужен секретный ключ.\n" + +#: g10/keyedit.c:575 +msgid "keyedit.save.okay" +msgstr "" + +#: g10/keyedit.c:576 +msgid "Save changes? " +msgstr "Сохранить изменения? " + +#: g10/keyedit.c:578 +#, fuzzy +msgid "keyedit.cancel.okay" +msgstr "" + +#: g10/keyedit.c:579 +msgid "Quit without saving? " +msgstr "Выйти без сохранения? " + +#: g10/keyedit.c:589 +#, fuzzy, c-format +msgid "update failed: %s\n" +msgstr "обновление не удалось: %s\n" + +#: g10/keyedit.c:596 +#, fuzzy, c-format +msgid "update secret failed: %s\n" +msgstr "обновление секрета не удалось: %s\n" + +#: g10/keyedit.c:603 +msgid "Key not changed so no update needed.\n" +msgstr "Ключ не изменился, обновление не нужно.\n" + +#: g10/keyedit.c:606 g10/keyedit.c:664 +#, fuzzy, c-format +msgid "update of trust db failed: %s\n" +msgstr "обновление базы данных доверия не удалось: %s\n" + +#: g10/keyedit.c:637 +msgid "keyedit.sign_all.okay" +msgstr "" + +#: g10/keyedit.c:638 +msgid "Really sign all user ids? " +msgstr "Действительно подписать все идентификаторы пользователя? " + +#: g10/keyedit.c:639 +msgid "Hint: Select the user ids to sign\n" +msgstr "Подсказка: выберите идентификаторы пользователя которые хотите подписать\n" + +#: g10/keyedit.c:675 +msgid "You must select at least one user id.\n" +msgstr "Вы должны выбрать хотя бы один идентификатор пользователя.\n" + +#: g10/keyedit.c:677 +msgid "You can't delete the last user id!\n" +msgstr "Вы не можете удалить последний идентификатор пользователя!\n" + +#: g10/keyedit.c:679 +msgid "keyedit.remove.uid.okay" +msgstr "" + +#: g10/keyedit.c:680 +#, fuzzy +msgid "Really remove all selected user ids? " +msgstr "Действительно удалить все выбранные идентификаторы пользователя? " + +#: g10/keyedit.c:681 +#, fuzzy +msgid "Really remove this user id? " +msgstr "Действительно удалить этот идентификатор пользователя? " + +#: g10/keyedit.c:704 +msgid "You must select at least one key.\n" +msgstr "Вы должны выбрать хотя бы один ключ.\n" + +#: g10/keyedit.c:706 +msgid "keyedit.remove.subkey.okay" +msgstr "" + +#: g10/keyedit.c:708 +#, fuzzy +msgid "Do you really want to delete the selected keys? " +msgstr "Вы действительно хотите удалить выбранные ключи? " + +#: g10/keyedit.c:709 +#, fuzzy +msgid "Do you really want to delete this key? " +msgstr "Вы действительно хотите удалить этот ключ? " + +#: g10/keyedit.c:746 +msgid "Invalid command (try \"help\")\n" +msgstr "Недопустимая команда (попробуйте \"help\")\n" + +#: g10/keyedit.c:1129 +#, c-format +msgid "No user id with index %d\n" +msgstr "Нет идентификатора пользователя с индексом %d\n" + +#: g10/keyedit.c:1174 +#, c-format +msgid "No secondary key with index %d\n" +msgstr "Нет дополнительного ключа с индексом %d\n" + +#: g10/mainproc.c:200 +#, c-format +msgid "public key decryption failed: %s\n" +msgstr "расшифровка открытым ключом не удалась %s\n" + +#: g10/mainproc.c:230 +#, c-format +msgid "decryption failed: %s\n" +msgstr "расшифровка не удалась: %s\n" + +#: g10/mainproc.c:247 +msgid "note: sender requested \"for-your-eyes-only\"\n" +msgstr "замечание: отправитель запросил \"только-для-Ваших-глаз\"\n" + +#: g10/mainproc.c:846 +#, c-format +msgid "Signature made %.*s using %s key ID %08lX\n" +msgstr "Подпись сделана %.*s, используя %s ключ %08lX\n" + +#: g10/mainproc.c:854 +msgid "BAD signature from \"" +msgstr "ПЛОХАЯ подпись от \"" + +#: g10/mainproc.c:855 +msgid "Good signature from \"" +msgstr "Хорошая подпись от \"" + +#: g10/mainproc.c:866 +#, c-format +msgid "Can't check signature: %s\n" +msgstr "Невозможно проверить подпись: %s\n" + +#: g10/passphrase.c:141 +msgid "" +"\n" +"You need a passphrase to unlock the secret key for\n" +"user: \"" +msgstr "" +"\n" +"Вам нужна ключевая фраза, чтобы отомкнуть ключ\n" +"пользователя: \"" + +#: g10/passphrase.c:150 +#, c-format +msgid "(%u-bit %s key, ID %08lX, created %s)\n" +msgstr "(%u-бит %s ключ, ID %08lX, создан %s)\n" + +# ################################ +# ####### Help msgids ############ +# ################################ +#: g10/passphrase.c:174 +msgid "passphrase.enter" +msgstr "" +"Bitte geben Sie die \"Passhrase\" ein; dies ist ein geheimer Satz der aus\n" +"beliebigen Zeichen bestehen kann. Was Sie eingegeben wird nicht angezeigt.\n" +"Zur ihrer eigenen Sicherbeit benutzen Sie biite einen Satz, den sie sich\n" +"gut merken kЖnne, der aber nicht leicht zu raten ist; Zitate und andere\n" +"bekannte Texte sind eine SCHLECHTE Wahl, da diese mit Sicherheit online\n" +"verfЭgbar sind und durch entsprechende Programme zum Raten der " +"\"Passphrase\"\n" +"benutzt werden. SДtze mit persЖnlicher Bedeutung, die auch noch durch\n" +"falsche Groъ-/Kleinschreibung und eingestreute Sonderzeichen verДndert " +"werden,\n" +"sind i.d.R. eine gute Wahl" + +#: g10/passphrase.c:174 +#, fuzzy +msgid "Enter pass phrase: " +msgstr "Введите ключевую фразу: %s\n" + +#: g10/passphrase.c:177 +msgid "passphrase.repeat" +msgstr "" +"Um sicher zu gehen, daъ Sie sich bei der Eingabe der \"Passphrase\" nicht\n" +"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n" +"Эbereinstimmen, wird die \"Passphrase\" akzeptiert." + +#: g10/passphrase.c:178 +#, fuzzy +msgid "Repeat pass phrase: " +msgstr "Повторите ключевую фразу: %s\n" + +#: g10/plaintext.c:102 +msgid "data not saved; use option \"--output\" to save it\n" +msgstr "данные не были сохранены; воспользуйтесь --\"output\" для сохранения\n" + +#: g10/plaintext.c:214 +#, fuzzy +msgid "detached_signature.filename" +msgstr "имя файла для отдельной подписи" + +#: g10/plaintext.c:215 +msgid "Please enter name of data file: " +msgstr "Пожалуйста, введите имя файла данных: " + +#: g10/plaintext.c:299 +#, c-format +msgid "can't open signed data '%s'\n" +msgstr "невозможно открыть подписанные данные '%s' .\n" + +#: g10/seckey-cert.c:56 +#, fuzzy, c-format +msgid "protection algorithm %d is not supported\n" +msgstr "алгоритм защиты %d не поддерживается\n" + +#: g10/seckey-cert.c:169 +msgid "Invalid passphrase; please try again ...\n" +msgstr "Неправильная ключевая фраза, попробуйте снова ...\n" + +#: g10/seckey-cert.c:215 +msgid "Warning: Weak key detected - please change passphrase again.\n" +msgstr "Предупреждение: обнаружен слабый ключ - смените ключевую фразу.\n" + +#: g10/sig-check.c:155 +msgid "" +"this is a PGP generated ElGamal key which is NOT secure for signatures!\n" +msgstr "этот ElGamal ключ, созданный PGP, не надежен для создания подписей!\n" + +#: g10/sig-check.c:165 +msgid "public key created in future (time warp or clock problem)\n" +msgstr "открытый ключ сгенерирован в будущем (искривление времени или неправильно установлены часы)\n" + +#: g10/sig-check.c:171 +#, c-format +msgid "warning: signature key expired %s\n" +msgstr "предупреждение: ключ подписи устарел %s\n" + +#: g10/trustdb.c:127 +msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n" +msgstr "База данных доверия разрушена: запустите \"gpgm --fix-trust-db\".\n" + +#: g10/trustdb.c:406 +#, c-format +msgid "chained sigrec %lu has a wrong owner\n" +msgstr "" + +#: g10/trustdb.c:453 +#, c-format +msgid "key %08lX: secret key without public key\n" +msgstr "секретный ключ %08lX: не имеет соответствующего открытого ключа.\n" + +#: g10/trustdb.c:458 +#, c-format +msgid "key %08lX: secret and public key don't match\n" +msgstr "" +"ключ %08lX: секретный и открытого ключи не совпадают.\n" + +#: g10/trustdb.c:469 +#, fuzzy, c-format +msgid "key %08lX: can't put it into the trustdb\n" +msgstr "ключ %08lX.%lu: невозможно положить в базу данных доверия\n" + +#: g10/trustdb.c:475 +#, fuzzy, c-format +msgid "key %08lX: query record failed\n" +msgstr "ключ %08lX: запрос записи не удался\n" + +#: g10/trustdb.c:484 +#, c-format +msgid "key %08lX: already in ultikey_table\n" +msgstr "ключ %08lX: уже в ultikey_table\n" + +#: g10/trustdb.c:491 +#, fuzzy, c-format +msgid "enum_secret_keys failed: %s\n" +msgstr "" + +#: g10/trustdb.c:964 +#, fuzzy, c-format +msgid "key %08lX.%lu, uid %02X%02X: no public key for signature %08lX\n" +msgstr "ключ %08lX.%lu, uid %02X%02X: нет открытого ключа для подписи %08lX\n" + +#: g10/trustdb.c:971 +#, fuzzy, c-format +msgid "key %08lX.%lu, uid %02X%02X: invalid %ssignature: %s\n" +msgstr "ключ %08lX: недопустимая само-подпись\n" + +#: g10/trustdb.c:1658 +#, fuzzy, c-format +msgid "key %08lX: insert trust record failed: %s\n" +msgstr "ключ %08lX.%lu: вставка доверительной записи не удалась: %s\n" + +#: g10/trustdb.c:1662 +#, c-format +msgid "key %08lX.%lu: inserted into trustdb\n" +msgstr "ключ %08lX.%lu: вставлен в базу данных доверия\n" + +#: g10/trustdb.c:1670 +#, c-format +msgid "key %08lX.%lu: created in future (time warp or clock problem)\n" +msgstr "ключ %08lX.%lu: сгенерирован в будущем (неправильно установлены часы)\n" + +#: g10/trustdb.c:1678 +#, c-format +msgid "key %08lX.%lu: expired at %s\n" +msgstr "ключ %08lX.%lu: срок действия истек %s\n" + +#: g10/trustdb.c:1687 +#, c-format +msgid "key %08lX.%lu: trust check failed: %s\n" +msgstr "ключ %08lX.%lu: проверка доверия не удалась: %s\n" + +#: g10/status.c:246 +msgid "No help available" +msgstr "Помощь отсутствует." + +#: g10/status.c:252 +#, c-format +msgid "No help available for '%s'" +msgstr "Помощь для '%s' отсутствует." + +#: g10/pubkey-enc.c:78 +#, c-format +msgid "anonymous receiver; trying secret key %08lX ...\n" +msgstr "анонимный получатель, пробуем секретный ключ %08lX ...\n" + +#: g10/pubkey-enc.c:84 +msgid "okay, we are the anonymous receiver.\n" +msgstr "Ок, мы -- анонимный получатель.\n" + +#: g10/pubkey-enc.c:183 +#, c-format +msgid "note: cipher algorithm %d not found in preferences\n" +msgstr "замечание: шифровальный алгоритм %d не найден в предпочтениях\n" + +#. do not overwrite +#: g10/openfile.c:58 +#, c-format +msgid "File '%s' exists. " +msgstr "Файл '%s' существует. " + +#: g10/openfile.c:59 +msgid "openfile.overwrite.okay" +msgstr "Вы желаете перезаписать файл (возможна потеря данных)" + +#: g10/openfile.c:60 +msgid "Overwrite (y/N)? " +msgstr "Переписать (y/N)? " + +#: g10/encr-data.c:74 +msgid "" +"Warning: Message was encrypted with a weak key in the symmetric cipher.\n" +msgstr "Предупреждение: сообщение было зашифровано, используя слабый ключ, в симметричном алгоритме шифрования.\n" + +#: g10/seskey.c:52 +msgid "weak key created - retrying\n" +msgstr "получился слабый ключ, пробуем еще раз\n" + +#: g10/seskey.c:57 +#, c-format +msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n" +msgstr "не получается избежать слабого ключа в симметричном алгоритме; пробовали %d раз!\n" + +#, fuzzy +#~ msgid "error reading sigrec: %s\n" +#~ msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n" + +#~ msgid "can't write keyring\n" +#~ msgstr "kann ключring nicht schreiben\n" + +#~ msgid "make a signature on a key in the keyring" +#~ msgstr "ключ signieren" + +#~ msgid "edit a key signature" +#~ msgstr "Bearbeiten der Signaturen eines ключs" + +#~ msgid "do not make any changes" +#~ msgstr "Keine wirklichen дnderungen durchfЭhren" + +#~ msgid "" +#~ "It's up to you to assign a value here; this value will never be exported\n" +#~ "to any 3rd party. We need it to implement the web-of-trust; it has nothing\n" +#~ "to do with the (implicitly created) web-of-certificates.\n" +#~ msgstr "" +#~ "Sie mЭssen selbt entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n" +#~ "wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n" +#~ "um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem " +#~ "(implizit\n" +#~ "erzeugten) \"Netz der Zertifikate\" zu tun.\n" + +#~ msgid "public and secret subkey created.\n" +#~ msgstr "жffentlicher und privater ключ erzeugt.\n" + +#~ msgid "No public key for %d signatures\n" +#~ msgstr "Kein Жffentlicher ключ fЭr %d Signaturen\n" + +#~ msgid "[User name not available] " +#~ msgstr "[Benuzername nicht verfЭgbar] " + +#~ msgid "This is a BAD signature!\n" +#~ msgstr "Dies ist eine FALSCHE Signatur!\n" + +#~ msgid "The signature could not be checked!\n" +#~ msgstr "Die Signatur konnte nicht geprЭft werden!\n" + +#~ msgid "Checking signatures of this public key certificate:\n" +#~ msgstr "Die Signaturen dieses Zertifikats werden ЭberprЭft:\n" + +#~ msgid "Do you want to remove some of the invalid signatures? " +#~ msgstr "MЖchten Sie einige der ungЭltigen Signaturen entfernen? " + +#~ msgid "there is a secret key for this public key!\n" +#~ msgstr "" +#~ "Es gibt einen privaten ключ zu diesem Жffentlichen ключ!\n" + +#~ msgid "use option \"--delete-secret-key\" to delete it first.\n" +#~ msgstr "" +#~ "Benutzen Sie das Kommando \"--delete-secret-key\", um ihn vorab zu " +#~ "entfernen.\n" + +#~ msgid "can't do that in batchmode without \"--yes\"\n" +#~ msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgefЭhrt werden.\n" + +#~ msgid "Delete this key from the keyring? " +#~ msgstr "Diesen ключ aus dem ключring lЖschen? " + +#~ msgid "This is a secret key! - really delete? " +#~ msgstr "Dies ist ein privater ключ! - Wirklich lЖschen? " + +#~ msgid "build_sigrecs: self-signature missing\n" +#~ msgstr "build_sigrecs: Selbst-Signatur fehlt\n" + +#~ msgid "build_sigrecs: key has been revoked\n" +#~ msgstr "build_sigrecs: ключ ist widerrufen\n" diff --git a/util/ChangeLog b/util/ChangeLog index 3c1dba658..c58f9f7e8 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,8 @@ +Thu Oct 22 16:25:49 1998 Michael Roth (mroth@nessie.de) + + * fileutil.c (make_basename): New. + (make_dirname): New. + Wed Oct 21 12:20:29 1998 Werner Koch (wk@isil.d.shuttle.de) * util.c (iobuf_flush): autoincreasing of a temp. iobuf diff --git a/util/fileutil.c b/util/fileutil.c index 2cedf0f9e..2169f9572 100644 --- a/util/fileutil.c +++ b/util/fileutil.c @@ -30,6 +30,61 @@ #include "ttyio.h" +/*************** + * Extract from a given path the filename component. + * + */ +char * +make_basename(const char *filepath) +{ + char *p; + + if ( !(p=strrchr(filepath, '/')) ) + #ifdef __MINGW32__ + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) + #endif + { + return m_strdup(filepath); + } + + return m_strdup(p+1); +} + + + +/*************** + * Extract from a given filename the path prepended to it. + * If their isn't a path prepended to the filename, a dot + * is returned ('.'). + * + */ +char * +make_dirname(const char *filepath) +{ + char *dirname; + int dirname_length; + char *p; + + if ( !(p=strrchr(filepath, '/')) ) + #ifdef __MINGW32__ + if ( !(p=strrchr(filepath, '\\')) ) + if ( !(p=strrchr(filepath, ':')) ) + #endif + { + return m_strdup("."); + } + + dirname_length = p-filepath; + dirname = m_alloc(dirname_length+1); + strncpy(dirname, filepath, dirname_length); + dirname[dirname_length] = 0; + + return dirname; +} + + + /**************** * Construct a filename from the NULL terminated list of parts. * Tilde expansion is done here.