See ChangeLog ;-). Key validation should now be faster

This commit is contained in:
Werner Koch 1998-11-13 19:41:41 +00:00
parent 95217d480d
commit 17ea875ab0
23 changed files with 535 additions and 190 deletions

129
ABOUT-NLS
View File

@ -137,7 +137,8 @@ Each translation team has its own mailing list, courtesy of Linux
International. You may reach your translation team at the address
`LL@li.org', replacing LL by the two-letter ISO 639 code for your
language. Language codes are *not* the same as the country codes given
in ISO 3166. The following translation teams exist, as of August 1998:
in ISO 3166. The following translation teams exist, as of December
1997:
Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
@ -172,79 +173,42 @@ Available Packages
==================
Languages are not equally supported in all packages. The following
matrix shows the current state of internationalization, as of August
1998. The matrix shows, in regard of each package, for which languages
matrix shows the current state of internationalization, as of December
1997. The matrix shows, in regard of each package, for which languages
PO files have been submitted to translation coordination.
Ready PO files cs da de el en es fi fr it
.----------------------------.
bash | [] [] |
bison | [] [] |
clisp | [] [] [] [] |
cpio | [] [] [] |
diffutils | [] [] [] |
enscript | [] [] [] [] |
fileutils | [] [] [] [] |
findutils | [] [] [] [] |
flex | [] [] |
gcal | [] [] |
gettext | [] [] [] [] [] |
grep | [] [] [] [] |
hello | [] [] [] [] [] |
id-utils | [] [] |
indent | [] [] |
libc | [] [] [] |
m4 | [] [] |
make | [] [] [] |
music | [] |
ptx | [] [] [] |
recode | [] [] [] [] |
sed | |
sh-utils | [] [] [] |
sharutils | [] [] [] [] [] |
tar | [] [] [] [] |
texinfo | [] [] [] |
textutils | [] [] [] [] |
wdiff | [] [] [] [] |
wget | [] [] [] [] |
`----------------------------'
cs da de el en es fi fr it
7 4 26 4 1 18 1 26 4
ja ko nl no pl pt ru sl sv
.----------------------------.
bash | [] | 3
bison | [] | 3
clisp | | 4
cpio | [] [] [] | 6
diffutils | [] [] | 5
enscript | [] [] | 6
fileutils | [] [] [] [] [] [] [] | 11
findutils | [] [] [] [] [] | 9
flex | [] [] | 4
gcal | [] [] [] | 5
gettext | [] [] [] [] [] [] [] | 13
grep | [] [] [] [] [] [] [] | 11
hello | [] [] [] [] [] [] [] | 12
id-utils | [] | 3
indent | [] [] [] | 5
libc | [] [] [] [] [] | 8
m4 | [] [] [] [] | 6
make | [] [] [] | 6
music | [] | 2
ptx | [] [] [] [] [] | 8
recode | [] [] [] [] [] | 9
sed | | 0
sh-utils | [] [] [] [] [] | 8
sharutils | [] [] | 7
tar | [] [] [] [] [] [] [] | 11
texinfo | [] | 4
textutils | [] [] [] [] [] | 9
wdiff | [] [] [] [] | 8
wget | [] | 5
`----------------------------'
18 teams ja ko nl no pl pt ru sl sv
29 domains 1 12 21 11 19 7 5 7 17 191
Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
.----------------------------------------------------.
bash | [] [] [] | 3
bison | [] [] [] | 3
clisp | [] [] [] [] | 4
cpio | [] [] [] [] [] [] | 6
diffutils | [] [] [] [] [] | 5
enscript | [] [] [] [] [] [] | 6
fileutils | [] [] [] [] [] [] [] [] [] [] | 10
findutils | [] [] [] [] [] [] [] [] [] | 9
flex | [] [] [] [] | 4
gcal | [] [] [] [] [] | 5
gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
grep | [] [] [] [] [] [] [] [] [] [] | 10
hello | [] [] [] [] [] [] [] [] [] [] [] | 11
id-utils | [] [] [] | 3
indent | [] [] [] [] [] | 5
libc | [] [] [] [] [] [] [] | 7
m4 | [] [] [] [] [] [] | 6
make | [] [] [] [] [] [] | 6
music | [] [] | 2
ptx | [] [] [] [] [] [] [] [] | 8
recode | [] [] [] [] [] [] [] [] [] | 9
sh-utils | [] [] [] [] [] [] [] [] | 8
sharutils | [] [] [] [] [] [] | 6
tar | [] [] [] [] [] [] [] [] [] [] [] | 11
texinfo | [] [] [] | 3
textutils | [] [] [] [] [] [] [] [] [] | 9
wdiff | [] [] [] [] [] [] [] [] | 8
`----------------------------------------------------'
17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
Some counters in the preceding matrix are higher than the number of
visible blocks let us expect. This is because a few extra PO files are
@ -257,23 +221,6 @@ distributed as such by its maintainer. There might be an observable
lag between the mere existence a PO file and its wide availability in a
distribution.
If August 1998 seems to be old, you may fetch a more recent copy of
this `ABOUT-NLS' file on most GNU archive sites.
Using `gettext' in new packages
===============================
If you are writing a freely available program and want to
internationalize it you are welcome to use GNU `gettext' in your
package. Of course the GNU Public License applies to your sources from
then if you include `gettext' directly in your distribution on but
since you are writing free software anyway this is no restriction.
Once the sources are change appropriately and the setup can handle to
use of `gettext' the only thing missing are the translations. The Free
Translation Project is also available for packages which are not
developed inside the GNU project. Therefore the information given above
applies also for every other Free Software Project. Contact
`translation@iro.umontreal.ca' to make the `.pot' files available to
the translation teams.
If December 1997 seems to be old, you may fetch a more recent copy
of this `ABOUT-NLS' file on most GNU archive sites.

4
README
View File

@ -43,8 +43,8 @@
IDEA (which is patented worldwide) and RSA (which is patented in
the United States until Sep 20, 2000).
GnuPG is in almost all aspects compatible with other OpenPGP
implementations.
GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
deatils.
The default algorithms are now DSA and ELGamal. ELGamal for signing
is still available, but due to the larger size of such signatures it

10
TODO
View File

@ -1,5 +1,12 @@
* Update the keyring on ftp.ggug.de
* I noticed, that we sometimes have only 3 items in atrustrecord, but
a next pointer ro more records - check wehther the reuse code really
works. Maybe this is the reason for the "Hmmm puiblic key lost"
* Update the keyring at ftp.ggug.de
* expire date is not shown in --edit-key for subkeys.
and prefs are not correctly listed for some keys???? (Brian)
* support for mpi/powerpc split is still combined or whatever
@ -84,6 +91,5 @@
* Add some stuff for DU cc
* use "passphrase" instead of "pass phrase"
* Use "user ID", "trustdb" and "WARNING".

View File

@ -14,6 +14,8 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
fpr = fingerprint: (fingerprint is in field 10)
2. Field: A letter describing the calculated trust, see doc/FAQ
This is a single letter, but be prepared that additional
information may follow in some future versions.
(not used for secret keys)
3. Field: length of key in bits.
4. Field: Algorithm: 1 = RSA
@ -30,6 +32,8 @@ ssb::1536:20:5CE086B5B5A18FF4:1998-07-07:0:::
because keyids may not be unique - a program may use this
number to access keys later.
9. Field: Ownertrust (primary public keys only)
This is a single letter, but be prepared that additional
information may follow in some future versions.
10. Field: User-ID. The value is quoted like a C string to avoid
control characters (the colon is quoted "\x3a").
@ -83,7 +87,11 @@ Record type 1:
1 byte value 2
3 bytes 'gpg' magic value
1 byte Version of the TrustDB
3 byte reserved
1 byte marginals needed
1 byte completes needed
1 byte max_cert_depth
The three items are used to check whether the cached
validity value from the dir record can be used.
1 u32 locked flags
1 u32 timestamp of trustdb creation
1 u32 timestamp of last modification
@ -110,8 +118,9 @@ Record type 2: (directory record)
1 u32 List of uid-records
1 u32 cache record
1 byte ownertrust
1 byte sigflag
20 byte reserved
1 byte dirflag
1 byte validity
19 byte reserved
Record type 3: (key record)

View File

@ -10,12 +10,12 @@ CVS Access
==========
Anonymous read-only CVS access is available:
cvs -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
use the password "anonymous". To check out the the complete
archive use:
cvs -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs checkout gnupg
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs checkout gnupg
This service is provided to help you in hunting bugs and not to deliver
stable snapshots; it may happen that it even does not compile, so please
@ -51,6 +51,7 @@ RFCs
2279 UTF-8, a transformation format of ISO 10646.
2440 OpenPGP.

View File

@ -1,28 +1,15 @@
GnuPG and OpenPGP
=================
The current OpenPGP draft expires 1999-02.
See RFC2440 for a description of OpenPGP.
OpenPGP is an Internet-Draft. Internet-Drafts are working
documents of the Internet Engineering Task Force (IETF), its areas,
and its working groups. Note that other groups may also distribute
working documents as Internet-Drafts.
Internet-Drafts are draft documents valid for a maximum of six
months and may be updated, replaced, or obsoleted by other documents
at any time. It is inappropriate to use Internet-Drafts as
reference material or to cite them other than as "work in progress."
To view the entire list of current Internet-Drafts, please check the
"1id-abstracts.txt" listing contained in the Internet-Drafts Shadow
Directories on ftp.is.co.za (Africa), ftp.nordu.net (Northern
Europe), ftp.nis.garr.it (Southern Europe), munnari.oz.au (Pacific
Rim), ftp.ietf.org (US East Coast), or ftp.isi.edu (US West Coast).
Compatibility Notes
===================
GnuPG (>=0.4.1) is in compliance with OpenPGP despite these exeptions:
GnuPG (>=0.4.1) is in compliance with RFC2440 despite these exeptions:
===> Please can someone check this <=========
* (5.1) The critical bit in signature subpackets is currently
ignored. This will be fixed soon.

View File

@ -345,6 +345,9 @@ B<--marginals-needed> I<n>
Number of marginally trusted users to introduce a new
key signator (defaults to 3)
B<--max-cert-depth> I<n>
Maximum depth of a certification chain (default is 5).
B<--cipher-algo> I<name>
Use I<name> as cipher algorithm. Running the program
with the command B<--version> yields a list of supported

View File

@ -1,3 +1,25 @@
Fri Nov 13 07:39:58 1998 Werner Koch <werner.koch@guug.de>
* trustdb.c (collect_paths): Removed a warning message.
(enum_trust_web): Removed.
(enum_cert_paths): New.
* pkclist.c (add_ownertrust): Changed to use enum_cert_paths.
(edit_ownertrust): Now list ceritficates on request.
(show_paths): New.
Wed Nov 11 18:05:44 1998 Werner Koch <werner.koch@guug.de>
* g10.c (main): New option --max-cert-depth
* tdbio.h: add new fields to ver and dir record.
* tdbio.c: read/write/dump of these fields.
(tdbio_db_matches_options): New.
* trustdb.c: replaced MAC_CERT_DEPTH by opt.max_cert_depth.
(do_check): cache validity and changed other functions
to reset the cached value.
* keylist.c (list_one): Now lists the ownertrust.
* mainproc.c (list_node): Ditto.
Tue Nov 10 10:08:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (g10_exit): Now looks at the new g10_errors_seen.

View File

@ -114,6 +114,7 @@ enum cmd_and_opt_values { aNull = 0,
oNoComment,
oCompletesNeeded,
oMarginalsNeeded,
oMaxCertDepth,
oLoadExtension,
oRFC1991,
oCipherAlgo,
@ -230,6 +231,7 @@ static ARGPARSE_OPTS opts[] = {
{ oNoComment, "no-comment", 0, N_("do not write comment packets")},
{ oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
{ oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
{ oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")},
@ -533,6 +535,7 @@ main( int argc, char **argv )
opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
opt.homedir = getenv("GNUPGHOME");
if( !opt.homedir || !*opt.homedir ) {
#ifdef __MINGW32__
@ -699,6 +702,7 @@ main( int argc, char **argv )
case oNoComment: opt.no_comment=1; break;
case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
case oNoOptions: break; /* no-options */
@ -819,6 +823,8 @@ main( int argc, char **argv )
log_error(_("completes-needed must be greater than 0\n"));
if( opt.marginals_needed < 2 )
log_error(_("marginals-needed must be greater than 1\n"));
if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 )
log_error(_("max-cert-depth must be in range 1 to 255\n"));
switch( opt.s2k_mode ) {
case 0:
log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));

View File

@ -207,7 +207,8 @@ list_keyblock( KBNODE keyblock, int secret )
if( pk->local_id )
printf("%lu", pk->local_id );
putchar(':');
/* fixme: add ownertrust here */
if( pk->local_id )
putchar( get_ownertrust_info( pk->local_id ) );
putchar(':');
}
else

View File

@ -483,7 +483,8 @@ list_node( CTX c, KBNODE node )
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
/* fixme: add ownertrust here */
if( c->local_id )
putchar( get_ownertrust_info( c->local_id ) );
putchar(':');
}
else

View File

@ -49,6 +49,7 @@ struct {
int no_comment;
int marginals_needed;
int completes_needed;
int max_cert_depth;
const char *homedir;
int skip_verify;
int compress_keys;

View File

@ -41,3 +41,8 @@ compress-algo 1
#charset koi8-r
# You may define aliases like this:
# alias mynames -u 0x12345678 -u 0x456789ab -z 9
# everytime you use --mynames, it will be expanded to the options
# in the above defintion. The name of the alias may not be abbreviated.

View File

@ -40,6 +40,49 @@
#define CONTROL_D ('D' - 'A' + 1)
static void
show_paths( ulong lid )
{
void *context = NULL;
unsigned otrust, validity;
int level;
while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){
char *p;
int rc;
size_t n;
u32 keyid[2];
PKT_public_key *pk ;
rc = keyid_from_lid( lid, keyid );
if( rc ) {
log_error("ooops: can't get keyid for lid %lu\n", lid);
return;
}
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_error("key %08lX: public key not found: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
return;
}
tty_printf("%*s%4u%c/%08lX.%lu %s \"",
level*2,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], lid, datestr_from_pk( pk ) );
p = get_user_id( keyid, &n );
tty_print_string( p, n ),
m_free(p);
tty_printf("\"\n\n");
}
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
}
/****************
* Returns true if an ownertrust has changed.
*/
@ -68,7 +111,7 @@ edit_ownertrust( ulong lid, int mode )
}
if( !mode ) {
tty_printf(_("No owner trust defined for %lu:\n"
tty_printf(_("No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""), lid,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
@ -115,7 +158,9 @@ edit_ownertrust( ulong lid, int mode )
break;
}
else if( *p == ans[0] || *p == ans[1] ) {
tty_printf(_("You will see a list of signators etc. here\n"));
tty_printf(_(
"Certificates leading to an ultimately trusted key:\n"));
show_paths( lid );
}
else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
break ; /* back to the menu */
@ -138,8 +183,8 @@ add_ownertrust( PKT_public_key *pk )
int rc;
void *context = NULL;
ulong lid;
unsigned trust;
int any=0;
unsigned otrust, validity;
int any=0, changed=0, any_undefined=0;
tty_printf(
_("Could not find a valid trust path to the key. Let's see whether we\n"
@ -152,22 +197,25 @@ _("Could not find a valid trust path to the key. Let's see whether we\n"
}
lid = pk->local_id;
while( !(rc=enum_trust_web( &context, &lid )) ) {
trust = get_ownertrust( lid );
if( trust == TRUST_UNDEFINED || trust == TRUST_EXPIRED ||
trust == TRUST_UNKNOWN ) {
while( enum_cert_paths( &context, &lid, &otrust, &validity ) != -1 ) {
any=1;
if( otrust == TRUST_UNDEFINED || otrust == TRUST_EXPIRED ||
otrust == TRUST_UNKNOWN ) {
any_undefined=1;
if( edit_ownertrust( lid, 0 ) )
any=1;
changed=1;
}
}
if( rc == -1 )
rc = 0;
enum_trust_web( &context, NULL ); /* close */
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
if( !any )
tty_printf(_("No owner trust values changed.\n\n") );
tty_printf(_("No path leading to one of our keys found.\n\n") );
else if( !any_undefined )
tty_printf(_("No certificates with undefined trust found.\n\n") );
else if( !changed )
tty_printf(_("No trust values changed.\n\n") );
return rc? rc : any? 0:-1;
return any? 0:-1;
}
/****************

View File

@ -830,6 +830,127 @@ update_keyblock( KBPOS *kbpos, KBNODE root )
}
/****************************************************************
********** Implemenation of a user ID database **************
****************************************************************/
#if 0
/****************
* Layout of the user ID db
*
* This user ID DB provides fast lookup of user ID, but the user ids are
* not in any specific order.
*
* A string "GnuPG user db", a \n.
* user ids of one key, delimited by \t,
* a # or ^ followed by a 20 byte fingerprint, followed by an \n
* The literal characters =, \n, \t, #, ^ must be replaced by a equal sign
* and their hex value.
*
* (We use Boyer/Moore pattern matching)
*/
/****************
* This compiles pattern to the distance table, the table will be allocate
* here and must be freed by using free().
* Returns: Ptr to new allocated Table
* Caller must free the table.
*/
static size_t *
compile_bm_table( const byte *pattern, size_t len )
{
ushort *dist;
int i;
dist = m_alloc_clear( 256 * sizeof *dist );
for(i=0; i < 256; i++ )
dist[i] = len;
for(i=0; i < len-1; i++ )
dTbl[p[i]] = len-i-1;
return dist;
}
/****************
* Search BUF of BUFLEN for pattern P of length PATLEN.
* dist is the Boyer/Moore distance table of 256 Elements,
* case insensitive search is done if IGNCASE is true (In this case
* the distance table has to compiled from uppercase chacaters and
* PAT must also be uppercase.
* Returns: Prt to maching string in BUF, or NULL if not found.
*/
static const *
do_bm_search( const byte *buf, size_t buflen,
const byte *pat, size_t patlen, size_t *dist, int igncase )
{
int i, j, k;
if( igncase ) {
int c, c1;
for( i = --patlen; i < buflen; i += dist[c1] )
for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
j--, k--, c=toupper(buf[k]) ) {
if( !j )
return buf+k;
}
}
else {
for( i = --patlen; i < buflen; i += dist[buf[i]] )
for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
if( !j )
return buf+k;
}
}
return NULL;
}
typedef struct {
size_t dist[256];
} *SCAN_USER_HANDLE;
static SCAN_USER_HANDLE
scan_user_file_open( const byte *name )
{
SCAN_USER_HANDLE hd;
size_t *dist;
int i;
hd = m_alloc_clear( sizeof *hd );
dist = hd->dist;
/* compile the distance table */
for(i=0; i < 256; i++ )
dist[i] = len;
for(i=0; i < len-1; i++ )
dTbl[p[i]] = len-i-1;
/* setup other things */
return hd;
}
static int
scan_user_file_close( SCAN_USER_HANDLE hd )
{
m_free( hd );
}
static int
scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
{
char record[1000];
/* read a record */
}
#endif
/****************************************************************
********** Functions which operates on regular keyrings ********

View File

@ -419,6 +419,9 @@ tdbio_set_dbname( const char *new_dbname, int create )
memset( &rec, 0, sizeof rec );
rec.r.ver.version = 2;
rec.r.ver.created = make_timestamp();
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record( &rec );
@ -511,6 +514,41 @@ create_hashtable( TRUSTREC *vr, int type )
}
int
tdbio_db_matches_options()
{
static int yes_no = -1;
if( yes_no == -1 ) {
TRUSTREC vr;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.marginals && !vr.r.ver.completes
&& !vr.r.ver.cert_depth )
{ /* special hack for trustdbs created by old versions of GnuPG */
vr.r.ver.marginals = opt.marginals_needed;
vr.r.ver.completes = opt.completes_needed;
vr.r.ver.cert_depth = opt.max_cert_depth;
rc = tdbio_write_record( &vr );
if( !rc && !in_transaction )
rc = tdbio_sync();
if( rc )
log_error( _("%s: error writing version record: %s\n"),
db_name, g10_errstr(rc) );
}
yes_no = vr.r.ver.marginals == opt.marginals_needed
&& vr.r.ver.completes == opt.completes_needed
&& vr.r.ver.cert_depth == opt.max_cert_depth;
}
return yes_no;
}
/****************
* Return the record number of the keyhash tbl or create a new one.
@ -839,19 +877,24 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
switch( rec->rectype ) {
case 0: fprintf(fp, "blank\n");
break;
case RECTYPE_VER: fprintf(fp, "version, kd=%lu, sd=%lu, free=%lu\n",
case RECTYPE_VER: fprintf(fp,
"version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d\n",
rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
rec->r.ver.firstfree );
rec->r.ver.firstfree,
rec->r.ver.marginals,
rec->r.ver.completes,
rec->r.ver.cert_depth );
break;
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
break;
case RECTYPE_DIR:
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, t=%02x",
rec->r.dir.lid,
rec->r.dir.keylist,
rec->r.dir.uidlist,
rec->r.dir.cacherec,
rec->r.dir.ownertrust );
if( rec->r.dir.dirflags & DIRF_VALVALID )
fprintf( fp, ", v=%02x", rec->r.dir.validity );
if( rec->r.dir.dirflags & DIRF_CHECKED ) {
if( rec->r.dir.dirflags & DIRF_VALID )
fputs(", valid", fp );
@ -863,7 +906,7 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
putc('\n', fp);
break;
case RECTYPE_KEY:
fprintf(fp, "key %lu, next=%lu, algo=%d, ",
fprintf(fp, "key %lu, n=%lu a=%d ",
rec->r.key.lid,
rec->r.key.next,
rec->r.key.pubkey_algo );
@ -1005,7 +1048,9 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
}
p += 2; /* skip "pgp" */
rec->r.ver.version = *p++;
p += 3; /* reserved bytes */
rec->r.ver.marginals = *p++;
rec->r.ver.completes = *p++;
rec->r.ver.cert_depth = *p++;
p += 4; /* lock flags */
rec->r.ver.created = buftoulong(p); p += 4;
rec->r.ver.modified = buftoulong(p); p += 4;
@ -1034,6 +1079,18 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
rec->r.dir.cacherec = buftoulong(p); p += 4;
rec->r.dir.ownertrust = *p++;
rec->r.dir.dirflags = *p++;
rec->r.dir.validity = *p++;
switch( rec->r.dir.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
if( rec->r.dir.lid != recnum ) {
log_error( "%s: dir LID != recnum (%lu,%lu)\n",
db_name, rec->r.dir.lid, (ulong)recnum );
@ -1137,7 +1194,10 @@ tdbio_write_record( TRUSTREC *rec )
BUG();
memcpy(p-1, "gpg", 3 ); p += 2;
*p++ = rec->r.ver.version;
p += 7; /* skip reserved bytes and lock flags */
*p++ = rec->r.ver.marginals;
*p++ = rec->r.ver.completes;
*p++ = rec->r.ver.cert_depth;
p += 4; /* skip lock flags */
ulongtobuf(p, rec->r.ver.created); p += 4;
ulongtobuf(p, rec->r.ver.modified); p += 4;
ulongtobuf(p, rec->r.ver.validated); p += 4;
@ -1157,6 +1217,7 @@ tdbio_write_record( TRUSTREC *rec )
ulongtobuf(p, rec->r.dir.cacherec); p += 4;
*p++ = rec->r.dir.ownertrust;
*p++ = rec->r.dir.dirflags;
*p++ = rec->r.dir.validity;
assert( rec->r.dir.lid == recnum );
break;

View File

@ -47,11 +47,12 @@
#define RECTYPE_FREE 254
#define DIRF_CHECKED 1 /* has been checkd - other bits are valid */
#define DIRF_CHECKED 1 /* has been checked - bits 1,2,3 are valid */
#define DIRF_VALID 2 /* This key is valid: There is at least */
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
#define DIRF_VALVALID 16 /* The validity field is valid */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
@ -77,6 +78,9 @@ struct trust_record {
union {
struct { /* version record: */
byte version; /* should be 2 */
byte marginals;
byte completes;
byte cert_depth;
ulong created; /* timestamp of trustdb creation */
ulong modified; /* timestamp of last modification */
ulong validated; /* timestamp of last validation */
@ -94,6 +98,7 @@ struct trust_record {
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel */
} dir;
struct { /* primary public key record */
ulong lid;
@ -168,6 +173,7 @@ 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_db_matches_options(void);
int tdbio_is_dirty(void);
int tdbio_sync(void);
int tdbio_begin_transaction(void);

View File

@ -42,8 +42,6 @@
#include "i18n.h"
#include "tdbio.h"
#define MAX_CERT_DEPTH 5
#if MAX_FINGERPRINT_LEN > 20
#error Must change structure of trustdb
#endif
@ -67,7 +65,7 @@ typedef struct trust_info TRUST_INFO;
struct trust_info {
ulong lid;
byte otrust; /* ownertrust (assigned trust) */
byte trust; /* calculated trust (validity) */
byte trust; /* calculated trust (validity) */
};
typedef struct trust_seg_list *TRUST_SEG_LIST;
@ -806,14 +804,15 @@ collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
continue; /* skip revoked signatures */
/* visit every signer only once (a signer may have
* signed multizple user IDs */
* signed more than one user ID) */
if( sigs_seen && ins_lid_table_item( sigs_seen,
rec.r.sig.sig[i].lid, 0) )
continue; /* we alread have this one */
continue; /* we already have this one */
read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) {
log_info("oops: lid %lu: sig %lu has rectype %d"
if( tmp.rectype != RECTYPE_SDIR )
log_info("oops: lid %lu: sig %lu has rectype %d"
" - skipped\n",
drec->r.dir.lid, tmp.recnum, tmp.rectype );
continue;
@ -892,7 +891,7 @@ verify_key( int max_depth, TRUSTREC *drec )
* but nothing more is known.
*/
static int
do_check( TRUSTREC *dr, unsigned *trustlevel )
do_check( TRUSTREC *dr, unsigned *validity )
{
if( !dr->r.dir.keylist ) {
log_error(_("Ooops, no keys\n"));
@ -903,10 +902,23 @@ do_check( TRUSTREC *dr, unsigned *trustlevel )
return G10ERR_TRUSTDB;
}
*trustlevel = verify_key( MAX_CERT_DEPTH, dr );
if( tdbio_db_matches_options()
&& (dr->r.dir.dirflags & DIRF_VALVALID)
&& dr->r.dir.validity )
*validity = dr->r.dir.validity;
else {
*validity = verify_key( opt.max_cert_depth, dr );
if( (*validity & TRUST_MASK) >= TRUST_UNDEFINED
&& tdbio_db_matches_options() ) {
/* update the cached validity value */
dr->r.dir.validity = (*validity & TRUST_MASK);
dr->r.dir.dirflags |= DIRF_VALVALID;
write_record( dr );
}
}
if( dr->r.dir.dirflags & DIRF_REVOKED )
*trustlevel |= TRUST_FLAG_REVOKED;
*validity |= TRUST_FLAG_REVOKED;
return 0;
}
@ -1496,7 +1508,10 @@ query_trust_info( PKT_public_key *pk )
/****************
* Enumerate all keys, which are needed to build all trust paths for
* the given key. This function does not return the key itself or
* the ultimate key.
* the ultimate key (the last point in cerificate chain). Only
* certificate chains which ends up at an ultimately trusted key
* are listed. If ownertrust or validity is not NULL, the corresponding
* value for the returned LID is also returned in these variable(s).
*
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function.
@ -1505,51 +1520,73 @@ query_trust_info( PKT_public_key *pk )
* to indicate EOF. LID does contain the next key used to build the web
* 4) Always call this function a last time with LID set to NULL,
* so that it can free its context.
*
* Returns: -1 on EOF or the level of the returned LID
*/
int
enum_trust_web( void **context, ulong *lid )
enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity )
{
#if 0
struct {
int init;
TRUST_SEG_LIST tsl_head;
TRUST_SEG_LIST tsl;
int idx;
} *ctx;
int rc;
int wipe=0;
TRUSTREC rec;
TRUST_INFO *tmppath;
TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
TRUST_SEG_LIST tsl;
if( !lid ) { /* release the context */
if( *context ) {
TRUST_SEG_LIST tsl2;
ctx = *context;
for(tsl = ctx->tsl_head; tsl; tsl = tsl2 ) {
tsl2 = tsl->next;
m_free( tsl );
}
*context = NULL;
}
return -1;
}
if( !*context ) {
asssert( *lid );
TRUST_INFO *tmppath;
TRUSTREC rec;
if( !lid )
return -1;
ctx = m_alloc_clear( sizeof *ctx );
*context = ctx;
/* collect the paths */
read_record( *lid, &rec, RECTYPE_DIR );
tmppath = m_alloc_clear( (MAX_CERT_DEPTH+1)* sizeof *tmppath );
trust_seg_list = NULL;
collect_paths( 0, MAX_CERT_DEPTH, 1, &rec, tmppath, &trust_seg_list );
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
tsl = NULL;
collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl );
m_free( tmppath );
/* and now print them */
for(tsl = trust_seg_list; tsl; tsl = tsl->next ) {
print_path( tsl->pathlen, tsl->path );
}
ctx->tsl_head = tsl;
ctx->tsl = ctx->tsl_head;
ctx->idx = 0;
}
else
ctx = *context;
if( !lid ) { /* release the context */
if( *
/* release the list */
for(tsl = trust_seg_list; tsl; tsl = tsl2 ) {
tsl2 = tsl->next;
m_free( tsl );
}
trust_seg_list = NULL;
while( ctx->tsl && ctx->idx >= tsl->pathlen ) {
ctx->tsl = ctx->tsl->next;
ctx->idx = 0;
}
#endif
return -1; /* eof */
tsl = ctx->tsl;
if( !tsl )
return -1; /* eof */
if( ownertrust )
*ownertrust = tsl->path[ctx->idx].otrust;
if( validity )
*validity = tsl->path[ctx->idx].trust;
*lid = tsl->path[ctx->idx].lid;
ctx->idx++;
return ctx->idx-1;
}
@ -1671,7 +1708,7 @@ query_trust_record( PKT_public_key *pk )
return get_dir_record( pk, &rec );
}
/* FIXME: Brauchen wir das?? */
int
clear_trust_checked_flag( PKT_public_key *pk )
{
@ -1682,11 +1719,14 @@ clear_trust_checked_flag( PKT_public_key *pk )
if( rc )
return rc;
if( !(rec.r.dir.dirflags & DIRF_CHECKED) )
/* check whether they are already reset */
if( !(rec.r.dir.dirflags & DIRF_CHECKED)
&& !(rec.r.dir.dirflags & DIRF_VALVALID) )
return 0;
/* reset the flag */
rec.r.dir.dirflags &= ~DIRF_CHECKED;
rec.r.dir.dirflags &= ~DIRF_VALVALID;
write_record( &rec );
do_sync();
return 0;
@ -2735,6 +2775,8 @@ update_trust_record( KBNODE keyblock, int recheck, int *modified )
if( rc )
rc = tdbio_cancel_transaction();
else {
drec.r.dir.dirflags |= DIRF_CHECKED;
drec.r.dir.dirflags &= ~DIRF_VALVALID;
write_record( &drec );
if( modified && tdbio_is_dirty() )
*modified = 1;

View File

@ -50,7 +50,8 @@ void update_trustdb( void );
int init_trustdb( int level, const char *dbname );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
int query_trust_info( PKT_public_key *pk );
int enum_trust_web( void **context, ulong *lid );
int enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity );
unsigned get_ownertrust( ulong lid );
int get_ownertrust_info( ulong lid );
byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n );

View File

@ -45,6 +45,7 @@ typedef struct {
int inarg;
int stopped;
const char *last;
void *aliases;
} internal; /* DO NOT CHANGE */
} ARGPARSE_ARGS;
@ -152,9 +153,10 @@ const char *memistr( const char *buf, size_t buflen, const char *sub );
char *mem2str( char *, const void *, size_t);
char *trim_spaces( char *string );
int string_count_chr( const char *string, int c );
int set_native_charset( const char *newset );
int set_native_charset( const char *newset );
char *native_to_utf8( const char *string );
char *utf8_to_native( const char *string );
int check_utf8_string( const char *string );
#define stricmp(a,b) strcasecmp((a),(b))

View File

@ -51,6 +51,7 @@
* struct {
* int index;
* const char *last;
* void *aliases;
* } internal; DO NOT CHANGE
* } ARGPARSE_ARGS;
*
@ -127,6 +128,12 @@
*
*/
typedef struct alias_def_s *ALIAS_DEF;
struct alias_def_s {
ALIAS_DEF next;
char *name; /* malloced buffer with name, \0, value */
const char *value; /* ptr into name */
};
static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
@ -139,7 +146,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
arg->internal.index = 0;
arg->internal.last = NULL;
arg->internal.inarg = 0;
arg->internal.stopped= 0;
arg->internal.stopped = 0;
arg->internal.aliases = NULL;
arg->err = 0;
arg->flags |= 1<<15; /* mark initialized */
if( *arg->argc < 0 )
@ -160,6 +168,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
s = "%s:%u: missing argument\n";
else if( arg->r_opt == -7 )
s = "%s:%u: invalid command\n";
else if( arg->r_opt == -10 )
s = "%s:%u: invalid alias definition\n";
else
s = "%s:%u: invalid option\n";
log_error(s, filename, *lineno );
@ -187,6 +197,16 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
static void
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
{
ALIAS_DEF a = m_alloc( sizeof *a );
a->name = name;
a->value = value;
a->next = (ALIAS_DEF)arg->internal.aliases;
(ALIAS_DEF)arg->internal.aliases = a;
}
/****************
* Get options from a file.
* Lines starting with '#' are comment lines.
@ -194,6 +214,8 @@ initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
* Valid keywords are all keywords from the long_opt list without
* the leading dashes. The special keywords "help", "warranty" and "version"
* are not valid here.
* The special keyword "alias" may be used to store alias definitions,
* which are later expanded like long options.
* Caller must free returned strings.
* If called with FP set to NULL command line args are parse instead.
*
@ -212,6 +234,7 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
char *buffer = NULL;
size_t buflen = 0;
int inverse=0;
int in_alias=0;
if( !fp ) /* same as arg_parse() in this case */
return arg_parse( arg, opts );
@ -234,9 +257,9 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
break;
index = i;
arg->r_opt = opts[index].short_opt;
if( inverse )
if( inverse ) /* this does not have an effect, hmmm */
arg->r_opt = -arg->r_opt;
if( !opts[index].short_opt ) /* unknown command/option */
if( !opts[index].short_opt ) /* unknown command/option */
arg->r_opt = (opts[index].flags & 256)? -7:-2;
else if( (opts[index].flags & 8) ) /* no argument */
arg->r_opt = -3; /* error */
@ -245,7 +268,9 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
break;
}
else if( state == 3 ) { /* no argument found */
if( !(opts[index].flags & 7) ) /* does not take an argument */
if( in_alias )
arg->r_opt = -3; /* error */
else if( !(opts[index].flags & 7) ) /* does not take an arg */
arg->r_type = 0; /* okay */
else if( (opts[index].flags & 8) ) /* no optional argument */
arg->r_type = 0; /* okay */
@ -254,7 +279,28 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
break;
}
else if( state == 4 ) { /* have an argument */
if( !(opts[index].flags & 7) ) /* does not take an argument */
if( in_alias ) {
if( !buffer )
arg->r_opt = -6;
else {
char *p;
buffer[i] = 0;
p = strpbrk( buffer, " \t" );
if( p ) {
*p++ = 0;
trim_spaces( p );
}
if( !p || !*p ) {
m_free( buffer );
arg->r_opt = -10;
}
else {
store_alias( arg, buffer, p );
}
}
}
else if( !(opts[index].flags & 7) ) /* does not take an arg */
arg->r_opt = -6; /* error */
else {
if( !buffer ) {
@ -296,8 +342,14 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
index = i;
arg->r_opt = opts[index].short_opt;
if( !opts[index].short_opt ) {
arg->r_opt = (opts[index].flags & 256)? -7:-2;
state = -1; /* skip rest of line and leave */
if( !strcmp( keyword, "alias" ) ) {
in_alias = 1;
state = 3;
}
else {
arg->r_opt = (opts[index].flags & 256)? -7:-2;
state = -1; /* skip rest of line and leave */
}
}
else
state = 3;
@ -344,10 +396,12 @@ optfile_parse( FILE *fp, const char *filename, unsigned *lineno,
static int
find_long_option( ARGPARSE_OPTS *opts, const char *keyword )
find_long_option( ARGPARSE_ARGS *arg,
ARGPARSE_OPTS *opts, const char *keyword )
{
int i;
size_t n;
ALIAS_DEF a;
/* Would be better if we can do a binary search, but it is not
possible to reorder our option table because we would mess
@ -358,7 +412,14 @@ find_long_option( ARGPARSE_OPTS *opts, const char *keyword )
for(i=0; opts[i].short_opt; i++ )
if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
return i;
#if 0
/* see whether it is an alias */
for( a= argds->internal.aliases; a; a = a->next )
if( !strcmp( a->name, keyword) )
return what_do_we_return_here;
#endif
/* not found, see whether it is an abbreviation */
/* aliases may not be abbreviated */
n = strlen( keyword );
for(i=0; opts[i].short_opt; i++ ) {
if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
@ -424,7 +485,7 @@ arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
argpos = strchr( s+2, '=' );
if( argpos )
*argpos = 0;
i = find_long_option( opts, s+2 );
i = find_long_option( arg, opts, s+2 );
if( argpos )
*argpos = '=';

View File

@ -126,7 +126,7 @@ make_dotlock( const char *file_to_lock, long timeout )
int
release_dotlock( const char *lockfile )
{
int pid = rad_lockfile( lockfile );
int pid = read_lockfile( lockfile );
if( pid == -1 ) {
log_error( "release_dotlock: lockfile error");
return -1;

View File

@ -285,6 +285,20 @@ utf8_to_native( const char *string )
}
/****************
* check whether string is a valid UTF8 string.
* Returns 0 = Okay
* 1 = Too short
* 2 = invalid encoding
*/
int
check_utf8_string( const char *string )
{
/*fixme */
return 0;
}
/*********************************************
********** missing string functions *********
*********************************************/