diff --git a/ChangeLog b/ChangeLog index 4e84473d9..e0091e20c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 13 19:22:46 CET 2000 Werner Koch + + * configure.in: Now uses the Docbook M$s from GPH. + Mon Jan 31 17:46:35 CET 2000 Werner Koch * Makefile.am: Re-added tools. By Rémi. diff --git a/acinclude.m4 b/acinclude.m4 index 4a8f0a2b2..20c92be52 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -663,4 +663,116 @@ if test $gnupg_cv_mkdir_takes_one_arg = yes ; then fi ]) + +dnl GPH_PROG_DOCBOOK() +dnl Check whether we have the needed Docbook environment +dnl and issue a warning if this is not the case. +dnl +dnl This test defines these variables for substitution: +dnl DB2HTML - command used to convert Docbook to HTML +dnl DB2TEX - command used to convert Docbook to TeX +dnl DB2MAN - command used to convert Docbook to man pages +dnl JADE - command to invoke jade +dnl JADETEX - command to invoke jadetex +dnl DSL_FOR_HTML - the stylesheet used to for the Docbook->HTML conversion +dnl The following make conditionals are defined +dnl HAVE_DB2MAN - defined when db2man is available +dnl HAVE_DB2TEX - defined when db2tex is available +dnl HAVE_DB2HTML - defined when db2html is available +dnl HAVE_DOCBOOK - defined when the entire Docbook environment is present +dnl HAVE_JADE - defined when jade is installed +dnl HAVE_JADETEX - defined when jadetex is installed +dnl +dnl (wk 2000-02-17) +dnl +AC_DEFUN(GPH_PROG_DOCBOOK, + [ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl + all=yes + AC_PATH_PROG(DB2MAN, docbook-to-man, no) + test "$DB2MAN" = no && all=no + AM_CONDITIONAL(HAVE_DB2MAN, test "$DB2MAN" != no ) + + AC_PATH_PROG(JADE, jade, no) + test "$JADE" = no && all=no + AM_CONDITIONAL(HAVE_JADE, test "$JADE" != no ) + + AC_PATH_PROG(JADETEX, jadetex, no) + test "$JADETEX" = no && all=no + AM_CONDITIONAL(HAVE_JADETEX, test "$JADETEX" != no ) + + stylesheet_dirs=' +/usr/local/lib/dsssl/stylesheets/docbook +/usr/local/share/dsssl/stylesheets/docbook +/usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh +/usr/local/share/sgml/stylesheet/dsssl/docbook/nwalsh +/usr/lib/dsssl/stylesheets/docbook +/usr/share/dsssl/stylesheets/docbook +/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh +/usr/share/sgml/stylesheet/dsssl/docbook/nwalsh +' + + AC_MSG_CHECKING(for TeX stylesheet) + dsl=none + for d in ${stylesheet_dirs}; do + file=${d}/print/docbook.dsl + if test -f $file; then + dsl=$file + break + fi + done + AC_MSG_RESULT([$dsl]) + okay=no + if test $dsl = none ; then + DB2TEX="$missing_dir/missing db2tex" + all=no + else + DB2TEX="$JADE -t tex -i tex -d $dsl" + okay=yes + fi + AC_SUBST(DB2TEX) + AM_CONDITIONAL(HAVE_DB2TEX, test $okay = yes ) + + if ( $ac_aux_dir/db2html.in --version) < /dev/null > /dev/null 2>&1; then + : + else + AC_ERROR([needed $ac_aux_dir/db2html.in not found]) + fi + + AC_MSG_CHECKING(for HTML stylesheet) + DSL_FOR_HTML="none" + for d in ${stylesheet_dirs}; do + file=${d}/html/docbook.dsl + if test -f $file; then + DSL_FOR_HTML=$file + break + fi + done + AC_MSG_RESULT([$DSL_FOR_HTML]) + okay=no + if test $DSL_FOR_HTML = none ; then + DB2HTML="$missing_dir/missing db2html" + all=no + else + DB2HTML="`cd $ac_aux_dir && pwd`/db2html --copyfiles" + okay=yes + fi + AC_SUBST(DB2HTML) + AC_SUBST(DSL_FOR_HTML) + AM_CONDITIONAL(HAVE_DB2HTML, test $okay = yes ) + + AM_CONDITIONAL(HAVE_DOCBOOK, test "$all" != yes ) + if test $all = no ; then + AC_MSG_WARN([[ +*** +*** It seems that the Docbook environment is not installed as required. +*** We will try to build everything, but if you either touch some files +*** or use a bogus make tool, you may run into problems. +*** Docbook is normally only needed to build the documentation. +***]]) + fi + ]) + + + + dnl *-*wedit:notab*-* Please keep this as the last line. diff --git a/cipher/ChangeLog b/cipher/ChangeLog index c0657d727..a81189702 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 13 19:22:46 CET 2000 Werner Koch + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + Mon Jan 31 16:37:34 CET 2000 Werner Koch * genprime.c (generate_elg_prime): Fixed returned factors which never diff --git a/cipher/md.c b/cipher/md.c index bc0a6c30d..680558db2 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -596,15 +596,22 @@ gcry_md_get( GCRY_MD_HD hd, int algo, byte *buffer, int buflen ) * Shortcut function to hash a buffer with a given algo. The only supported * algorithm is RIPE-MD. The supplied digest buffer must be large enough * to store the resulting hash. No error is returned, the function will - * abort on an invalite algo. DISABLED_ALGOS are ignored here. + * abort on an invalid algo. DISABLED_ALGOS are ignored here. */ void gcry_md_hash_buffer( int algo, char *digest, const char *buffer, size_t length) { if( algo == GCRY_MD_RMD160 ) rmd160_hash_buffer( digest, buffer, length ); - else - BUG(); + else { /* for the others we do not have a fast function, so + * we use the normal functions to do it */ + GCRY_MD_HD h = md_open( algo, 0 ); + if( !h ) + BUG(); /* algo not available */ + md_write( h, (byte*)buffer, length ); + md_final( h ); + memcpy( digest, md_read( h, algo ), md_digest_length( algo ) ); + } } static int diff --git a/configure.in b/configure.in index ac926d640..fddb93d2a 100644 --- a/configure.in +++ b/configure.in @@ -164,8 +164,7 @@ AC_PROG_CPP AC_ISC_POSIX AC_PROG_INSTALL AC_PROG_AWK -AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no) -AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes) +GPH_PROG_DOCBOOK dnl @@ -687,6 +686,7 @@ GNUPG_FIX_HDR_VERSION(gcrypt/gcrypt.h, GCRYPT_VERSION) AC_OUTPUT_COMMANDS([ +chmod +x scripts/db2html chmod +x gcrypt/gcrypt-config cat >gnupg-defs.tmp <$@ +endif + +if HAVE_DB2TEX +%.ps : %.dvi dvips -o $@ $< +%.tex : %.sgml + $(DB2TEX) -V generate-book-toc $< > $@ -if MAINTAINER_MODE - -%.1 : %.sgml - docbook-to-man $< >$@ - -%.texi : %.xml - docbook2texi $< >$@ - -%.xml : %.sgml - sgml2xml -x lower $< >$@ +%.dvi : %.tex + $(JADETEX) $< +endif +if HAVE_DB2HTML +%.html : %.sgml + $(DB2HTML) --nosplit $< endif - diff --git a/doc/gcryptref.sgml b/doc/gcryptref.sgml index abc3efb20..bf9d5092d 100644 --- a/doc/gcryptref.sgml +++ b/doc/gcryptref.sgml @@ -18,7 +18,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA --> - + @@ -27,6 +29,33 @@ ]> + + +The &libgcrypt; Reference Manual +Version &packageversion; + +2000-03-13 + + +2000 +Free Software Foundation, Inc. + + + +Please direct questions, bug reports, or suggestions concerning +this manual to the mailing list gnupg-doc@gnupg.org. + + + +This manual may be redistributed under the terms of the +GNU +General Public License. + + + + + + &libgcrypt; Reference Pages @@ -37,7 +66,7 @@ &digestref; - + &pubkeyref; diff --git a/doc/version.sgml.in b/doc/version.sgml.in new file mode 100644 index 000000000..d78bda934 --- /dev/null +++ b/doc/version.sgml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/g10/ChangeLog b/g10/ChangeLog index 21b24880e..6cd97d675 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,11 @@ +Mon Mar 13 19:22:46 CET 2000 Werner Koch + + * build-paket.c (do_user_id): Save offset where name has been stored. + + * ringedit.c : Add new access method KBXF + + * kbxfile.c: New. + Mon Feb 21 22:43:01 CET 2000 Werner Koch * kbx.h: New. diff --git a/g10/Makefile.am b/g10/Makefile.am index bc83ad9c2..9018c1450 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -4,7 +4,9 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl EXTRA_DIST = OPTIONS pubring.asc options.skel OMIT_DEPENDENCIES = zlib.h zconf.h LDFLAGS = -static @LDFLAGS@ @DYNLINK_LDFLAGS@ -needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la +# we need to add libutil.la a second time because we have to resolve +# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon. +needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la ../jnlib/libjnlib.la ../util/libutil.la #noinst_PROGRAMS = gpgd bin_PROGRAMS = gpg @@ -22,6 +24,9 @@ common_source = \ skclist.c \ ringedit.c \ kbnode.c \ + kbx.h \ + kbxblob.c \ + kbxfile.c \ main.h \ mainproc.c \ armor.c \ diff --git a/g10/build-packet.c b/g10/build-packet.c index 2f3eebea3..5772b13be 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -196,6 +196,7 @@ static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ) { write_header(out, ctb, uid->len); + uid->stored_at = iobuf_tell( out ); /* what a hack */ if( iobuf_write( out, uid->name, uid->len ) ) return GPGERR_WRITE_FILE; return 0; diff --git a/g10/kbx.h b/g10/kbx.h index 9e61ebbd0..6508d3eab 100644 --- a/g10/kbx.h +++ b/g10/kbx.h @@ -21,6 +21,12 @@ #ifndef GPG_KBX_H #define GPG_KBX_H 1 +#include "keydb.h" + +typedef struct kbxblob *KBXBLOB; + +int kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock ); +void kbx_release_blob ( KBXBLOB blob ); #endif /*GPG_KBX_H*/ diff --git a/g10/kbxblob.c b/g10/kbxblob.c index cf3bb7a22..c7804870c 100644 --- a/g10/kbxblob.c +++ b/g10/kbxblob.c @@ -16,27 +16,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - *********************************************** - * adler_cksum() is based on the zlib code with these conditions: - * - * Copyright (C) 1995-1998 Mark Adler - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. */ @@ -51,9 +30,11 @@ the beginning of the Blob. The first record of a plain KBX file has a special format: u32 length of the first record - u32 magic 'KBXf' + byte Blob type (1) byte version number (1) - b[3] reserved + byte reserved + byte reserved + u32 magic 'KBXf' byte marginals used for validity calculation of this file byte completes ditto. byte cert_depth ditto. @@ -61,8 +42,8 @@ The first record of a plain KBX file has a special format: The standard KBX Blob looks like this: u32 length of this blob (including these 4 bytes) - byte version number (1) - byte reserved + byte Blob type (2) + byte version number of this blob type (1) u16 Blob flags bit 0 = contains secret key material @@ -98,6 +79,8 @@ The standard KBX Blob looks like this: u8 all_validity u16 reserved u32 recheck_after + u32 Newest timestamp in the keyblock (useful for KS syncronsiation?) + u32 Blob created at u32 size of reserved space (not including this field) reserved space @@ -107,7 +90,7 @@ The standard KBX Blob looks like this: maybe we put a sigture here later. - u32 adler checksum + b16 MD5 checksum (useful for KS syncronsiation) * */ @@ -120,6 +103,8 @@ The standard KBX Blob looks like this: #include #include +#include "iobuf.h" +#include "util.h" #include "kbx.h" /* special values of the signature status */ @@ -135,22 +120,21 @@ The standard KBX Blob looks like this: struct kbxblob_key { char fpr[20]; u32 off_kid; - ulong off_kid_addr; /* where it is stored in the datablock */ + ulong off_kid_addr; u16 flags; }; struct kbxblob_uid { - u32 off; - ulong off_addr; /* where it is stored in the datablock */ + ulong off_addr; u32 len; u16 flags; - byte validity + byte validity; }; struct keyid_list { struct keyid_list *next; int seqno; - char kid[8]; -} + byte kid[8]; +}; struct kbxblob { int nkeys; @@ -161,49 +145,10 @@ struct kbxblob { u32 *sigs; struct keyid_list *temp_kids; -} *KBXBLOB; + IOBUF buf; /* the KBX is stored here */ +}; -static u32 -adler_cksum ( const byte *buf, size_t len ) -{ - unsigned long s1 = 1; - unsigned long s2 = 0; - - #define X_BASE 65521L /* largest prime smaller than 65536 */ - #define X_NMAX 5552 /* largest n such that */ - /* 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - #define X_DO1(buf,i) {s1 += buf[i]; s2 += s1;} - #define X_DO2(buf,i) X_DO1(buf,i); X_DO1(buf,i+1); - #define X_DO4(buf,i) X_DO2(buf,i); X_DO2(buf,i+2); - #define X_DO8(buf,i) X_DO4(buf,i); X_DO4(buf,i+4); - #define X_DO16(buf) X_DO8(buf,0); X_DO8(buf,8); - while ( len ) { - int k = len < NMAX ? len : NMAX; - len -= k; - while ( k >= 16 ) { - DO16(buf); - buf += 16; - k -= 16; - } - if ( k ) { - do { - s1 += *buf++; - s2 += s1; - } while ( --k ); - } - s1 %= BASE; - s2 %= BASE; - } - #undef X_BASE - #undef X_NMAX - #undef X_DO1 - #undef X_DO2 - #undef X_DO4 - #undef X_DO8 - #undef X_DO16 - return ( s2 << 16 ) | s1; -} /* Note: this functions are only used for temportay iobufs and therefore @@ -211,14 +156,14 @@ adler_cksum ( const byte *buf, size_t len ) static void put8 ( IOBUF out, byte a ) { - iobuf_put ( out, a ) + iobuf_put ( out, a ); } static void put16 ( IOBUF out, u16 a ) { iobuf_put ( out, a>>8 ); - iobuf_put ( out, a ) + iobuf_put ( out, a ); } static void @@ -227,7 +172,7 @@ put32 ( IOBUF out, u32 a ) iobuf_put (out, a>> 24); iobuf_put (out, a>> 16); iobuf_put (out, a>> 8); - iobuf_put (out, a) ) + iobuf_put (out, a ); } static void @@ -245,7 +190,7 @@ static void put32at ( IOBUF out, u32 a, size_t pos ) { size_t n; - byte *p, + byte *p; iobuf_flush_temp ( out ); p = iobuf_get_temp_buffer( out ); @@ -269,37 +214,44 @@ temp_store_kid ( KBXBLOB blob, PKT_public_key *pk ) struct keyid_list *k, *r; k = gcry_xmalloc ( sizeof *k ); - k->kid = pk->keyid; + k->kid[0] = pk->keyid[0] >> 24 ; + k->kid[1] = pk->keyid[0] >> 16 ; + k->kid[2] = pk->keyid[0] >> 8 ; + k->kid[3] = pk->keyid[0] ; + k->kid[4] = pk->keyid[0] >> 24 ; + k->kid[5] = pk->keyid[0] >> 16 ; + k->kid[6] = pk->keyid[0] >> 8 ; + k->kid[7] = pk->keyid[0] ; k->seqno = 0; k->next = blob->temp_kids; blob->temp_kids = k; for ( r=k; r; r = r->next ) { - k->seqno++ + k->seqno++; } return k->seqno; } static void -put_stored_kid( IOBUF a, KBXBLOB blob, int seqno ) +put_stored_kid( KBXBLOB blob, int seqno ) { struct keyid_list *r; for ( r = blob->temp_kids; r; r = r->next ) { if( r->seqno == seqno ) { - putn ( a, r->kid, 8 ); + putn ( blob->buf, r->kid, 8 ); return; } } BUG(); } -static int +static void release_kid_list ( struct keyid_list *kl ) { struct keyid_list *r, *r2; - for ( r = blob->temp_kids; r; r = r2 ) { + for ( r = kl; r; r = r2 ) { r2 = r->next; gcry_free( r ); } @@ -310,19 +262,18 @@ static int create_key_part( KBXBLOB blob, KBNODE keyblock ) { KBNODE node; - byte fpr[MAX_FINGERPRINT_LEN]; size_t fprlen; int n; for ( n=0, node = keyblock; node; node = node->next ) { - if ( node->pkt->pkttype == PKT_PUBLIC_KEY: + if ( node->pkt->pkttype == PKT_PUBLIC_KEY || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { PKT_public_key *pk = node->pkt->pkt.public_key; fingerprint_from_pk( pk, blob->keys[n].fpr, &fprlen ); if ( fprlen != 20 ) { /*v3 fpr - shift right and fill with zeroes*/ assert( fprlen == 16 ); - memmove( blob->keys[n]+4, blob->keys[n].fpr, 16); + memmove( blob->keys[n].fpr+4, blob->keys[n].fpr, 16); memset( blob->keys[n].fpr, 0, 4 ); blob->keys[n].off_kid = temp_store_kid( blob, pk ); } @@ -351,7 +302,6 @@ create_uid_part( KBXBLOB blob, KBNODE keyblock ) if ( node->pkt->pkttype == PKT_USER_ID ) { PKT_user_id *u = node->pkt->pkt.user_id; - blob->uids[n].off = 0; /* must calculate this later */ blob->uids[n].len = u->len; blob->uids[n].flags = 0; blob->uids[n].validity = 0; @@ -382,13 +332,14 @@ create_sig_part( KBXBLOB blob, KBNODE keyblock ) static int -create_blob_header( IOBUF a, KBXBLOB blob ) +create_blob_header( KBXBLOB blob ) { + IOBUF a = blob->buf; int i; put32 ( a, 0 ); /* blob length, needs fixup */ - put8 ( a, 1 ); /* version number */ - put8 ( a, 0 ); /* reserved */ + put8 ( a, 2 ); /* blob type */ + put8 ( a, 1 ); /* blob type version */ put16 ( a, 0 ); /* blob flags */ put32 ( a, 0 ); /* offset to the keyblock, needs fixup */ @@ -398,7 +349,7 @@ create_blob_header( IOBUF a, KBXBLOB blob ) put16 ( a, 20 + 8 + 2 + 2 ); /* size of key info */ for ( i=0; i < blob->nkeys; i++ ) { putn ( a, blob->keys[i].fpr, 20 ); - blob->keys[i].off_kid_addr = iobuf_tell ( out ); + blob->keys[i].off_kid_addr = iobuf_tell ( a ); put32 ( a, 0 ); /* offset to keyid, fixed up later */ put16 ( a, blob->keys[i].flags ); put16 ( a, 0 ); /* reserved */ @@ -407,7 +358,7 @@ create_blob_header( IOBUF a, KBXBLOB blob ) put16 ( a, blob->nuids ); put16 ( a, 4 + 4 + 2 + 1 + 1 ); /* size of uid info */ for ( i=0; i < blob->nuids; i++ ) { - blob->uids[i].off_addr = iobuf_tell ( out ); + blob->uids[i].off_addr = iobuf_tell ( a ); put32 ( a, 0 ); /* offset to userid, fixed up later */ put32 ( a, blob->uids[i].len ); put16 ( a, blob->uids[i].flags ); @@ -425,16 +376,18 @@ create_blob_header( IOBUF a, KBXBLOB blob ) put8 ( a, 0 ); /* validity of all user IDs */ put16 ( a, 0 ); /* reserved */ put32 ( a, 0 ); /* time of next recheck */ + put32 ( a, 0 ); /* newest timestamp (none) */ + put32 ( a, make_timestamp() ); /* creation time */ put32 ( a, 0 ); /* size of reserved space */ - /* reserved space (which is currently 0) */ + /* reserved space (which is currently of size 0) */ /* We need to store the keyids for all v3 keys because those key IDs are * not part of the fingerprint. While we are doing that, we fixup all * the keyID offsets */ for ( i=0; i < blob->nkeys; i++ ) { if ( blob->keys[i].off_kid ) { /* this is a v3 one */ - put32at ( a, iobuf_tell(), blob->keys[i].off_kid_addr ); - put_stored_kid ( a, blob, blob->keys[i].off_kid ); + put32at ( a, iobuf_tell(a), blob->keys[i].off_kid_addr ); + put_stored_kid ( blob, blob->keys[i].off_kid ); } else { /* the better v4 key IDs - just store an offset 8 bytes back */ put32at ( a, blob->keys[i].off_kid_addr-8, @@ -447,38 +400,60 @@ create_blob_header( IOBUF a, KBXBLOB blob ) } static int -create_blob_keyblock( IOBUF a, KBXBLOB blob, KBNODE keyblock ) +create_blob_keyblock( KBXBLOB blob, KBNODE keyblock ) { + IOBUF a = blob->buf; KBNODE node; int rc; + int nsig; - for ( node = keyblock; node; node = node->next ) { - /* we must get some offset into thge keyblock and do some - * fixups */ - rc = build_packet ( fp, node->pkt ); + for ( nsig = 0, node = keyblock; node; node = node->next ) { + rc = build_packet ( a, node->pkt ); if ( rc ) { - log_error("build_packet(%d) for kbxblob failed: %s\n", + gpg_log_error("build_packet(%d) for kbxblob failed: %s\n", node->pkt->pkttype, gpg_errstr(rc) ); return GPGERR_WRITE_FILE; } + if ( node->pkt->pkttype == PKT_USER_ID ) { + PKT_user_id *u = node->pkt->pkt.user_id; + /* build_packet has set the offset of the name into u ; + * now we can do the fixup */ + put32at ( a, u->stored_at, blob->uids[nsig].off_addr ); + nsig++; + } } + assert( nsig == blob->nsigs ); return 0; } static int -create_blob_trailer( IOBUF a, KBXBLOB blob ) +create_blob_trailer( KBXBLOB blob ) { + IOBUF a = blob->buf; return 0; } static int -create_blob_finish( IOBUF a, KBXBLOB blob ) +create_blob_finish( KBXBLOB blob ) { + IOBUF a = blob->buf; + byte *p; + size_t n; + /* write a placeholder for the checksum */ + put32( a, 0 ); put32( a, 0 ); put32( a, 0 ); put32( a, 0 ); + /* get the memory area */ + iobuf_flush_temp ( a ); + p = iobuf_get_temp_buffer ( a ); + n = iobuf_get_temp_length ( a ); + assert( n >= 20 ); /* fixup the length */ - /* optionally we could sign the whole stuff at this point */ - /* write the checksum */ + put32at ( a, 0, n ); + + /* calculate and store the MD5 checksum */ + gcry_md_hash_buffer( GCRY_MD_MD5, p + n - 16, p, n - 16 ); + return 0; } @@ -488,9 +463,7 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock ) { int rc = 0; KBNODE node; - struct kbxblob *blob; - int nkey, nuid, nsig; - IOBUF a = NULL; + KBXBLOB blob; *retkbx = NULL; blob = gcry_calloc (1, sizeof *blob ); @@ -507,56 +480,63 @@ kbx_create_blob ( KBXBLOB *retkbx, KBNODE keyblock ) case PKT_PUBLIC_SUBKEY: case PKT_SECRET_SUBKEY: blob->nkeys++; break; case PKT_USER_ID: blob->nuids++; break; - case PKT_SIGNATURE: blob->nsigs++, break; + case PKT_SIGNATURE: blob->nsigs++; break; + default: break; } } - blob->nkeys = gcry_calloc ( blob->nkeys, sizeof ( blob->keys ) ); - blob->nuids = gcry_calloc ( blob->nuids, sizeof ( blob->uids ) ); - blob->nsigs = gcry_calloc ( blob->nsigs, sizeof ( blob->sigs ) ); - if ( !blob->nkeys || !blob->nuids || !blob->nsigs ) { + blob->keys = gcry_calloc ( blob->nkeys, sizeof ( blob->keys ) ); + blob->uids = gcry_calloc ( blob->nuids, sizeof ( blob->uids ) ); + blob->sigs = gcry_calloc ( blob->nsigs, sizeof ( blob->sigs ) ); + if ( !blob->keys || !blob->uids || !blob->sigs ) { rc = GCRYERR_NO_MEM; goto leave; } - rc = create_key_part ( blob, keyblock ), + rc = create_key_part ( blob, keyblock ); if( rc ) goto leave; - rc = create_uid_part ( blob, keyblock ), + rc = create_uid_part ( blob, keyblock ); if( rc ) goto leave; - rc = create_sig_part ( blob, keyblock ), + rc = create_sig_part ( blob, keyblock ); if( rc ) goto leave; - a = iobuf_temp(); - rc = create_blob_header ( a, blob ); + blob->buf = iobuf_temp(); + rc = create_blob_header ( blob ); if( rc ) goto leave; - rc = create_blob_keyblock ( a, blob, keyblock ); + rc = create_blob_keyblock ( blob, keyblock ); if( rc ) goto leave; - rc = create_blob_trailer ( a, blob ); + rc = create_blob_trailer ( blob ); if( rc ) goto leave; - rc = create_blob_finish ( a, blob ); + rc = create_blob_finish ( blob ); if( rc ) goto leave; - /* now we take the iobuf and copy it to the output */ - *retkbx = blob; - failure: - if( a ) - iobuf_cancel( a ); + leave: release_kid_list( blob->temp_kids ); + blob->temp_kids = NULL; if ( rc ) { - gcry_free( blob->nkeys ); - gcry_free( blob->nuids ); - gcry_free( blob->nsigs ); - gcry_free( blob ); + kbx_release_blob ( blob ); } return rc; } +void +kbx_release_blob ( KBXBLOB blob ) +{ + if( !blob ) + return; + if( blob->buf ) + iobuf_cancel( blob->buf ); + gcry_free( blob->keys ); + gcry_free( blob->uids ); + gcry_free( blob->sigs ); + gcry_free( blob ); +} diff --git a/g10/kbxfile.c b/g10/kbxfile.c new file mode 100644 index 000000000..215259ee4 --- /dev/null +++ b/g10/kbxfile.c @@ -0,0 +1,45 @@ +/* kbxfile.c - KBX file handling + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/**************** + * We will change the whole system to use only KBX. This file here + * will implements the methods needed to operate on plain KBXfiles. + * Most stuff from getkey and ringedit will be replaced by stuff here. + * To make things even mor easier we will only allow one updateable kbxfile + * and optionally some read-only files. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "kbx.h" + + +int +kbxfile_search_by_fpr( void ) +{ + return -1; +} + diff --git a/g10/keydb.h b/g10/keydb.h index 221c01c64..05aac77d3 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -57,7 +57,8 @@ struct kbnode_struct { enum resource_type { rt_UNKNOWN = 0, rt_RING = 1, - rt_GDBM = 2 + rt_GDBM = 2, + rt_KBXF = 3 }; diff --git a/g10/packet.h b/g10/packet.h index 495871cf2..02f701799 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -162,6 +162,8 @@ typedef struct { } PKT_comment; typedef struct { + ulong stored_at; /* the stream offset where it was stored + * by build-packet */ int len; /* length of the name */ char name[1]; } PKT_user_id; diff --git a/g10/ringedit.c b/g10/ringedit.c index df51be695..2fa79fd74 100644 --- a/g10/ringedit.c +++ b/g10/ringedit.c @@ -60,6 +60,7 @@ #include "options.h" #include "main.h" #include "i18n.h" +#include "kbx.h" #ifdef MKDIR_TAKES_ONE_ARG @@ -96,6 +97,12 @@ static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); +static int do_kbxf_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf, + const char *fname ); +static int do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root ); +static int do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); +static int do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root ); + #ifdef HAVE_LIBGDBM static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ); static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, @@ -206,6 +213,7 @@ add_keyblock_resource( const char *url, int force, int secret ) /* Do we have an URL? * gnupg-gdbm:filename := this is a GDBM resource + * gnupg-kbxf:filename := this is a KBX file resource * gnupg-ring:filename := this is a plain keyring * filename := See what is is, but create as plain keyring. */ @@ -214,6 +222,10 @@ add_keyblock_resource( const char *url, int force, int secret ) rt = rt_RING; resname += 11; } + else if( !strncmp( resname, "gnupg-kbxf:", 11 ) ) { + rt = rt_KBXF; + resname += 11; + } else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) { rt = rt_GDBM; resname += 11; @@ -259,8 +271,17 @@ add_keyblock_resource( const char *url, int force, int secret ) rt = rt_GDBM; else if( magic == 0xce9a5713 ) log_error("%s: endianess does not match\n", url ); - else + else { + char buf[8]; + rt = rt_RING; + if( fread( buf, 8, 1, fp) == 1 ) { + if( !memcmp( buf+4, "KBXf", 4 ) + && buf[0] == 1 && buf[1] == 1 ) { + rt = rt_KBXF; + } + } + } } else /* maybe empty: assume ring */ rt = rt_RING; @@ -277,6 +298,7 @@ add_keyblock_resource( const char *url, int force, int secret ) goto leave; case rt_RING: + case rt_KBXF: iobuf = iobuf_open( filename ); if( !iobuf && !force ) { rc = GPGERR_OPEN_FILE; @@ -341,6 +363,7 @@ add_keyblock_resource( const char *url, int force, int secret ) #endif break; + #ifdef HAVE_LIBGDBM case rt_GDBM: resource_table[i].dbf = gdbm_open( filename, 0, @@ -458,6 +481,10 @@ search( PACKET *pkt, KBPOS *kbpos, int secret ) rc = keyring_search( pkt, kbpos, resource_table[i].iobuf, resource_table[i].fname ); break; + case rt_KBXF: + rc = do_kbxf_search( pkt, kbpos, resource_table[i].iobuf, + resource_table[i].fname ); + break; #ifdef HAVE_LIBGDBM case rt_GDBM: { PKT_public_key *req_pk = pkt->pkt.public_key; @@ -706,6 +733,8 @@ read_keyblock( KBPOS *kbpos, KBNODE *ret_root ) switch( kbpos->rt ) { case rt_RING: return keyring_read( kbpos, ret_root ); + case rt_KBXF: + return do_kbxf_read( kbpos, ret_root ); #ifdef HAVE_LIBGDBM case rt_GDBM: return do_gdbm_read( kbpos, ret_root ); @@ -762,6 +791,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) kbpos->valid = 0; switch( kbpos->rt ) { case rt_RING: + case rt_KBXF: kbpos->fp = iobuf_open( rentry->fname ); if( !kbpos->fp ) { log_error("can't open `%s'\n", rentry->fname ); @@ -788,6 +818,11 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) return GPGERR_GENERAL; rc = keyring_enum( kbpos, ret_root, mode == 11 ); break; + case rt_KBXF: + if( !kbpos->fp ) + return GPGERR_GENERAL; + rc = do_kbxf_enum( kbpos, ret_root, mode == 11 ); + break; #ifdef HAVE_LIBGDBM case rt_GDBM: rc = do_gdbm_enum( kbpos, ret_root ); @@ -812,6 +847,7 @@ enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root ) else { switch( kbpos->rt ) { case rt_RING: + case rt_KBXF: if( kbpos->fp ) { iobuf_close( kbpos->fp ); kbpos->fp = NULL; @@ -852,6 +888,9 @@ insert_keyblock( KBPOS *kbpos, KBNODE root ) case rt_RING: rc = keyring_copy( kbpos, 1, root ); break; + case rt_KBXF: + rc = do_kbxf_copy( kbpos, 1, root ); + break; #ifdef HAVE_LIBGDBM case rt_GDBM: rc = do_gdbm_store( kbpos, root, 0 ); @@ -881,6 +920,9 @@ delete_keyblock( KBPOS *kbpos ) case rt_RING: rc = keyring_copy( kbpos, 2, NULL ); break; + case rt_KBXF: + rc = do_kbxf_copy( kbpos, 2, NULL ); + break; #ifdef HAVE_LIBGDBM case rt_GDBM: log_debug("deleting gdbm keyblock is not yet implemented\n"); @@ -909,6 +951,9 @@ update_keyblock( KBPOS *kbpos, KBNODE root ) case rt_RING: rc = keyring_copy( kbpos, 3, root ); break; + case rt_KBXF: + rc = do_kbxf_copy( kbpos, 3, root ); + break; #ifdef HAVE_LIBGDBM case rt_GDBM: rc = do_gdbm_store( kbpos, root, 1 ); @@ -1543,6 +1588,478 @@ keyring_copy( KBPOS *kbpos, int mode, KBNODE root ) return rc; } + +/**************************************************************** + ********** Functions which operate on KBX files **************** + ****************************************************************/ + +/**************** + * search a KBX file return 0 if found, -1 if not found or an errorcode. + */ +static int +do_kbxf_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) +{ + int rc; + PACKET pkt; + int save_mode; + ulong offset; + int pkttype = req->pkttype; + PKT_public_key *req_pk = req->pkt.public_key; + PKT_secret_key *req_sk = req->pkt.secret_key; + + init_packet(&pkt); + save_mode = set_packet_list_mode(0); + kbpos->rt = rt_RING; + kbpos->valid = 0; + + #if HAVE_DOSISH_SYSTEM || 1 + assert(!iobuf); + iobuf = iobuf_open( fname ); + if( !iobuf ) { + log_error("%s: can't open keyring file\n", fname); + rc = GPGERR_KEYRING_OPEN; + goto leave; + } + #else + if( iobuf_seek( iobuf, 0 ) ) { + log_error("can't rewind keyring file\n"); + rc = GPGERR_KEYRING_OPEN; + goto leave; + } + #endif + + while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) { + if( pkt.pkttype == PKT_SECRET_KEY ) { + PKT_secret_key *sk = pkt.pkt.secret_key; + + if( req_sk->timestamp == sk->timestamp + && req_sk->pubkey_algo == sk->pubkey_algo + && !cmp_seckey( req_sk, sk) ) + break; /* found */ + } + else if( pkt.pkttype == PKT_PUBLIC_KEY ) { + PKT_public_key *pk = pkt.pkt.public_key; + + if( req_pk->timestamp == pk->timestamp + && req_pk->pubkey_algo == pk->pubkey_algo + && !cmp_pubkey( req_pk, pk ) ) + break; /* found */ + } + else + BUG(); + free_packet(&pkt); + } + if( !rc ) { + kbpos->offset = offset; + kbpos->valid = 1; + } + + leave: + free_packet(&pkt); + set_packet_list_mode(save_mode); + #if HAVE_DOSISH_SYSTEM || 1 + iobuf_close(iobuf); + #endif + return rc; +} + + +static int +do_kbxf_read( KBPOS *kbpos, KBNODE *ret_root ) +{ + PACKET *pkt; + int rc; + RESTBL *rentry; + KBNODE root = NULL; + IOBUF a; + int in_cert = 0; + + if( !(rentry=check_pos(kbpos)) ) + return GPGERR_GENERAL; + + a = iobuf_open( rentry->fname ); + if( !a ) { + log_error("can't open `%s'\n", rentry->fname ); + return GPGERR_OPEN_FILE; + } + + if( !kbpos->valid ) + log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset ); + if( iobuf_seek( a, kbpos->offset ) ) { + log_error("can't seek to %lu\n", kbpos->offset); + iobuf_close(a); + return GPGERR_KEYRING_OPEN; + } + + pkt = gcry_xmalloc( sizeof *pkt ); + init_packet(pkt); + kbpos->count=0; + while( (rc=parse_packet(a, pkt)) != -1 ) { + if( rc ) { /* ignore errors */ + if( rc != GPGERR_UNKNOWN_PACKET ) { + log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) ); + rc = GPGERR_INV_KEYRING; + goto ready; + } + kbpos->count++; + free_packet( pkt ); + init_packet( pkt ); + continue; + } + /* make a linked list of all packets */ + switch( pkt->pkttype ) { + case PKT_COMPRESSED: + log_error("skipped compressed packet in keyring\n" ); + free_packet(pkt); + init_packet(pkt); + break; + + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + if( in_cert ) + goto ready; + in_cert = 1; + default: + kbpos->count++; + if( !root ) + root = new_kbnode( pkt ); + else + add_kbnode( root, new_kbnode( pkt ) ); + pkt = gcry_xmalloc( sizeof *pkt ); + init_packet(pkt); + break; + } + } + ready: + kbpos->valid = 0; + if( rc == -1 && root ) + rc = 0; + + if( rc ) + release_kbnode( root ); + else + *ret_root = root; + free_packet( pkt ); + gcry_free( pkt ); + iobuf_close(a); + return rc; +} + + +static int +do_kbxf_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ) +{ + PACKET *pkt; + int rc; + RESTBL *rentry; + KBNODE root = NULL; + + if( !(rentry=check_pos(kbpos)) ) + return GPGERR_GENERAL; + + if( kbpos->pkt ) { + root = new_kbnode( kbpos->pkt ); + kbpos->pkt = NULL; + } + + pkt = gcry_xmalloc( sizeof *pkt ); + init_packet(pkt); + while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) { + if( rc ) { /* ignore errors */ + if( rc != GPGERR_UNKNOWN_PACKET ) { + log_error("read_keyblock: read error: %s\n", gpg_errstr(rc) ); + rc = GPGERR_INV_KEYRING; + goto ready; + } + free_packet( pkt ); + init_packet( pkt ); + continue; + } + /* make a linked list of all packets */ + switch( pkt->pkttype ) { + case PKT_COMPRESSED: + log_error("skipped compressed packet in keyring\n" ); + free_packet(pkt); + init_packet(pkt); + break; + + case PKT_PUBLIC_KEY: + case PKT_SECRET_KEY: + if( root ) { /* store this packet */ + kbpos->pkt = pkt; + pkt = NULL; + goto ready; + } + root = new_kbnode( pkt ); + pkt = gcry_xmalloc( sizeof *pkt ); + init_packet(pkt); + break; + + default: + /* skip pakets at the beginning of a keyring, until we find + * a start packet; issue a warning if it is not a comment */ + if( !root && pkt->pkttype != PKT_COMMENT + && pkt->pkttype != PKT_OLD_COMMENT ) { + break; + } + if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE + ||pkt->pkttype == PKT_COMMENT + ||pkt->pkttype == PKT_OLD_COMMENT )) ) { + init_packet(pkt); + break; + } + add_kbnode( root, new_kbnode( pkt ) ); + pkt = gcry_xmalloc( sizeof *pkt ); + init_packet(pkt); + break; + } + } + ready: + if( rc == -1 && root ) + rc = 0; + + if( rc ) + release_kbnode( root ); + else + *ret_root = root; + free_packet( pkt ); + gcry_free( pkt ); + + return rc; +} + + +/**************** + * Perform insert/delete/update operation. + * mode 1 = insert + * 2 = delete + * 3 = update + */ +static int +do_kbxf_copy( KBPOS *kbpos, int mode, KBNODE root ) +{ + RESTBL *rentry; + IOBUF fp, newfp; + int rc=0; + char *bakfname = NULL; + char *tmpfname = NULL; + + if( !(rentry = check_pos( kbpos )) ) + return GPGERR_GENERAL; + if( kbpos->fp ) + BUG(); /* not allowed with such a handle */ + + if( opt.dry_run ) + return 0; + + lock_rentry( rentry ); + + /* open the source file */ + fp = iobuf_open( rentry->fname ); + if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */ + KBNODE kbctx, node; + + /* insert: create a new file */ + newfp = iobuf_create( rentry->fname ); + if( !newfp ) { + log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno)); + unlock_rentry( rentry ); + return GPGERR_OPEN_FILE; + } + else if( !opt.quiet ) + log_info(_("%s: keyring created\n"), rentry->fname ); + + kbctx=NULL; + while( (node = walk_kbnode( root, &kbctx, 0 )) ) { + if( (rc = build_packet( newfp, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, gpg_errstr(rc) ); + iobuf_cancel(newfp); + unlock_rentry( rentry ); + return GPGERR_WRITE_FILE; + } + } + if( iobuf_close(newfp) ) { + log_error("%s: close failed: %s\n", rentry->fname, strerror(errno)); + unlock_rentry( rentry ); + return GPGERR_CLOSE_FILE; + } + if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) { + log_error("%s: chmod failed: %s\n", + rentry->fname, strerror(errno) ); + unlock_rentry( rentry ); + return GPGERR_WRITE_FILE; + } + return 0; + } + if( !fp ) { + log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) ); + rc = GPGERR_OPEN_FILE; + goto leave; + } + + /* create the new file */ + #ifdef USE_ONLY_8DOT3 + /* Here is another Windoze bug?: + * you cant rename("pubring.gpg.tmp", "pubring.gpg"); + * but rename("pubring.gpg.tmp", "pubring.aaa"); + * works. So we replace .gpg by .bak or .tmp + */ + if( strlen(rentry->fname) > 4 + && !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) { + bakfname = gcry_xmalloc( strlen( rentry->fname ) + 1 ); + strcpy(bakfname,rentry->fname); + strcpy(bakfname+strlen(rentry->fname)-4, ".bak"); + tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 1 ); + strcpy(tmpfname,rentry->fname); + strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp"); + } + else { /* file does not end with gpg; hmmm */ + bakfname = gcry_xmalloc( strlen( rentry->fname ) + 5 ); + strcpy(stpcpy(bakfname,rentry->fname),".bak"); + tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 ); + strcpy(stpcpy(tmpfname,rentry->fname),".tmp"); + } + #else + bakfname = gcry_xmalloc( strlen( rentry->fname ) + 2 ); + strcpy(stpcpy(bakfname,rentry->fname),"~"); + tmpfname = gcry_xmalloc( strlen( rentry->fname ) + 5 ); + strcpy(stpcpy(tmpfname,rentry->fname),".tmp"); + #endif + newfp = iobuf_create( tmpfname ); + if( !newfp ) { + log_error("%s: can't create: %s\n", tmpfname, strerror(errno) ); + iobuf_close(fp); + rc = GPGERR_OPEN_FILE; + goto leave; + } + + if( mode == 1 ) { /* insert */ + /* copy everything to the new file */ + rc = copy_all_packets( fp, newfp ); + if( rc != -1 ) { + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, gpg_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + rc = 0; + } + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy first part to the new file */ + rc = copy_some_packets( fp, newfp, kbpos->offset ); + if( rc ) { /* should never get EOF here */ + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, gpg_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + /* skip this keyblock */ + assert( kbpos->count ); + rc = skip_some_packets( fp, kbpos->count ); + if( rc ) { + log_error("%s: skipping %u packets failed: %s\n", + rentry->fname, kbpos->count, gpg_errstr(rc)); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + } + + if( mode == 1 || mode == 3 ) { /* insert or update */ + KBNODE kbctx, node; + + /* append the new data */ + kbctx=NULL; + while( (node = walk_kbnode( root, &kbctx, 0 )) ) { + if( (rc = build_packet( newfp, node->pkt )) ) { + log_error("build_packet(%d) failed: %s\n", + node->pkt->pkttype, gpg_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + rc = GPGERR_WRITE_FILE; + goto leave; + } + } + kbpos->valid = 0; + } + + if( mode == 2 || mode == 3 ) { /* delete or update */ + /* copy the rest */ + rc = copy_all_packets( fp, newfp ); + if( rc != -1 ) { + log_error("%s: copy to %s failed: %s\n", + rentry->fname, tmpfname, gpg_errstr(rc) ); + iobuf_close(fp); + iobuf_cancel(newfp); + goto leave; + } + rc = 0; + } + + /* close both files */ + if( iobuf_close(fp) ) { + log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) ); + rc = GPGERR_CLOSE_FILE; + goto leave; + } + if( iobuf_close(newfp) ) { + log_error("%s: close failed: %s\n", tmpfname, strerror(errno) ); + rc = GPGERR_CLOSE_FILE; + goto leave; + } + /* if the new file is a secring, restrict the permissions */ + #ifndef HAVE_DOSISH_SYSTEM + if( rentry->secret ) { + if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) { + log_error("%s: chmod failed: %s\n", + tmpfname, strerror(errno) ); + rc = GPGERR_WRITE_FILE; + goto leave; + } + } + #endif + + /* rename and make backup file */ + if( !rentry->secret ) { /* but not for secret keyrings */ + #ifdef HAVE_DOSISH_SYSTEM + remove( bakfname ); + #endif + if( rename( rentry->fname, bakfname ) ) { + log_error("%s: rename to %s failed: %s\n", + rentry->fname, bakfname, strerror(errno) ); + rc = GPGERR_RENAME_FILE; + goto leave; + } + } + #ifdef HAVE_DOSISH_SYSTEM + remove( rentry->fname ); + #endif + if( rename( tmpfname, rentry->fname ) ) { + log_error("%s: rename to %s failed: %s\n", + tmpfname, rentry->fname,strerror(errno) ); + rc = GPGERR_RENAME_FILE; + if( rentry->secret ) { + log_info(_( + "WARNING: 2 files with confidential information exists.\n")); + log_info(_("%s is the unchanged one\n"), rentry->fname ); + log_info(_("%s is the new one\n"), tmpfname ); + log_info(_("Please fix this possible security flaw\n")); + } + goto leave; + } + + leave: + unlock_rentry( rentry ); + gcry_free(bakfname); + gcry_free(tmpfname); + return rc; +} + + #ifdef HAVE_LIBGDBM /**************************************************************** diff --git a/scripts/db2html.in b/scripts/db2html.in new file mode 100755 index 000000000..ba35afbc1 --- /dev/null +++ b/scripts/db2html.in @@ -0,0 +1,151 @@ +#!/bin/sh +# db2html.in - Docbook to HTML rendering (wk 2000-02-15) +# +# Copyright (C) 2000 Free Software Foundation +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +nosplit=no +copyfiles=no +stylesheet=@DSL_FOR_HTML@ +JADE=@JADE@ + +usage () { + echo 'usage: db2html [--nosplit] [--copyfiles] filename' >&2 + exit 1 +} + + +while test "`echo $1 | head -c1`" = "-"; do + case $1 in + --version) + cat <&2 + exit 1 + ;; + esac + shift +done + +if test $# = 1; then + input="$1" +else + usage +fi + +# grep the document type +doctype=`grep -i '\&2 +else + echo "DOCTYPE is '$doctype'" >&2 +fi + +output="`basename $input| sed 's/\.sgml$//'`.html" + + +if test $nosplit = yes; then + echo "running jade on '$input' ..." >&2 + $JADE -d $stylesheet -t sgml -i html -V nochunks $input > $output + echo "$output created" + exit 0 +fi + +if test -d html ; then + : +else + if mkdir html; then + echo "'html' directory created" >&2 + else + echo "failed to create 'html' directory" >&2 + exit 1 + fi +fi + +outputdir="html/`basename $input| sed 's/\.sgml$//'`" + +if test -d $outputdir ; then + : +else + if mkdir $outputdir; then + echo "'$outputdir' created" >&2 + else + echo "failed to create '$outputdir'" >&2 + exit 1 + fi +fi +echo "creating html pages in '$outputdir' ..." >&2 +if test "$input" = "`basename $input`"; then + inp="../../$input" +else + inp="$input" +fi +echo "running jade on '$inp' ..." >&2 +(cd $outputdir && $JADE -t sgml -i html -d $stylesheet $inp ) +echo "html version in '$outputdir' created" >&2 + +# break out all filerefs and copy them to the outputdirectory +# fixme: handling of path components is wrong +if test $copyfiles = yes; then + echo "looking for filerefs ..." >&2 + for file in `nsgmls -i html $input \ + | awk '/^AFILEREF[ \t]+CDATA/ {print $3}'`; do + d=$outputdir/`basename $file` + if cat $file > $outputdir/`basename $file` ; then + echo " $file -> $d" >&2 + fi + done +fi + +mainfile=`ls $outputdir/${doctype}* | head -1` + +cat > $output <$output + + +$mainfile + + + +EOF + +echo "$output created with link to '$mainfile'" >&2 + +exit 0 + diff --git a/tools/Makefile.am b/tools/Makefile.am index 92e008dfd..057f883e5 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -2,8 +2,10 @@ EXTRA_DIST = lspgpot INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -needed_libs = ../gcrypt/libgcrypt.la \ - ../util/libutil.la ../jnlib/libjnlib.la @INTLLIBS@ +# we need to add libutil.la a second time because we have to resolve +# gpg_log_ in some libjnlib modules. - very ugly - should be removed soon. +needed_libs = ../util/libutil.la ../gcrypt/libgcrypt.la \ + ../jnlib/libjnlib.la ../util/libutil.la @INTLLIBS@ noinst_PROGRAMS = mpicalc bftest clean-sat mk-tdata shmtest