From 17ea875ab0abd267eb720f8c82ac668e90cc3669 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 13 Nov 1998 19:41:41 +0000 Subject: [PATCH] See ChangeLog ;-). Key validation should now be faster --- ABOUT-NLS | 129 ++++++++++++++--------------------------------- README | 4 +- TODO | 10 +++- doc/DETAILS | 15 ++++-- doc/HACKING | 5 +- doc/OpenPGP | 21 ++------ doc/gpg.1pod | 3 ++ g10/ChangeLog | 22 ++++++++ g10/g10.c | 6 +++ g10/keylist.c | 3 +- g10/mainproc.c | 3 +- g10/options.h | 1 + g10/options.skel | 5 ++ g10/pkclist.c | 76 +++++++++++++++++++++++----- g10/ringedit.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ g10/tdbio.c | 75 ++++++++++++++++++++++++--- g10/tdbio.h | 8 ++- g10/trustdb.c | 116 ++++++++++++++++++++++++++++-------------- g10/trustdb.h | 3 +- include/util.h | 4 +- util/argparse.c | 79 +++++++++++++++++++++++++---- util/dotlock.c | 2 +- util/strgutil.c | 14 +++++ 23 files changed, 535 insertions(+), 190 deletions(-) diff --git a/ABOUT-NLS b/ABOUT-NLS index 249a4b5b0..28d38c76f 100644 --- a/ABOUT-NLS +++ b/ABOUT-NLS @@ -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. diff --git a/README b/README index f25ff6f91..513495a06 100644 --- a/README +++ b/README @@ -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 diff --git a/TODO b/TODO index b0b835ac3..bb237e6a3 100644 --- a/TODO +++ b/TODO @@ -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". diff --git a/doc/DETAILS b/doc/DETAILS index 0ac48bdc1..e3c49948e 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -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) diff --git a/doc/HACKING b/doc/HACKING index f30928432..e4c1aa972 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -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. diff --git a/doc/OpenPGP b/doc/OpenPGP index 647d891f0..62f9cbac0 100644 --- a/doc/OpenPGP +++ b/doc/OpenPGP @@ -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. diff --git a/doc/gpg.1pod b/doc/gpg.1pod index aacefcbb3..e299b3809 100644 --- a/doc/gpg.1pod +++ b/doc/gpg.1pod @@ -345,6 +345,9 @@ B<--marginals-needed> I Number of marginally trusted users to introduce a new key signator (defaults to 3) +B<--max-cert-depth> I + Maximum depth of a certification chain (default is 5). + B<--cipher-algo> I Use I as cipher algorithm. Running the program with the command B<--version> yields a list of supported diff --git a/g10/ChangeLog b/g10/ChangeLog index af6daf002..1f072a962 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,25 @@ +Fri Nov 13 07:39:58 1998 Werner Koch + + * 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 + + * 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. diff --git a/g10/g10.c b/g10/g10.c index 7deb3dac6..86dd90104 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -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")); diff --git a/g10/keylist.c b/g10/keylist.c index 257e869e4..f2ded0455 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -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 diff --git a/g10/mainproc.c b/g10/mainproc.c index c85787407..c21516deb 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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 diff --git a/g10/options.h b/g10/options.h index 0ad465177..1502d7453 100644 --- a/g10/options.h +++ b/g10/options.h @@ -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; diff --git a/g10/options.skel b/g10/options.skel index 1d7ebd7fc..3ce6e5aa8 100644 --- a/g10/options.skel +++ b/g10/options.skel @@ -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. + diff --git a/g10/pkclist.c b/g10/pkclist.c index 2f3928716..f56708c63 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -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; } /**************** diff --git a/g10/ringedit.c b/g10/ringedit.c index ebeceb16a..d12afa6dc 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -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 ******** diff --git a/g10/tdbio.c b/g10/tdbio.c index 11b2dcf25..bac8a3364 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -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; diff --git a/g10/tdbio.h b/g10/tdbio.h index e44f8c3e4..d2d369bed 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -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); diff --git a/g10/trustdb.c b/g10/trustdb.c index c145525fa..4cdb7e8db 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -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; diff --git a/g10/trustdb.h b/g10/trustdb.h index 4dc8b2ccb..04b243526 100644 --- a/g10/trustdb.h +++ b/g10/trustdb.h @@ -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 ); diff --git a/include/util.h b/include/util.h index 6d39d23e0..acb4de418 100644 --- a/include/util.h +++ b/include/util.h @@ -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)) diff --git a/util/argparse.c b/util/argparse.c index a75ef3467..29870e977 100644 --- a/util/argparse.c +++ b/util/argparse.c @@ -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 = '='; diff --git a/util/dotlock.c b/util/dotlock.c index 42d47117c..917b90dd5 100644 --- a/util/dotlock.c +++ b/util/dotlock.c @@ -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; diff --git a/util/strgutil.c b/util/strgutil.c index 82ec69007..ce7603808 100644 --- a/util/strgutil.c +++ b/util/strgutil.c @@ -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 ********* *********************************************/