From: Christian Grothoff Date: Sat, 24 Apr 2010 13:46:07 +0000 (+0000) Subject: blocklib X-Git-Tag: initial-import-from-subversion-38251~22013 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=8d9525a642c6bd74a2903ccb6358da8ebb081864;p=oweals%2Fgnunet.git blocklib --- diff --git a/src/block/Makefile.am b/src/block/Makefile.am new file mode 100644 index 000000000..b9585c260 --- /dev/null +++ b/src/block/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = -I$(top_srcdir)/src/include + +if MINGW + WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +endif + +if USE_COVERAGE + AM_CFLAGS = --coverage +endif + +lib_LTLIBRARIES = libgnunetblock.la + +libgnunetblock_la_SOURCES = \ + block.c +libgnunetblock_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la + +check_PROGRAMS = \ + test_block + +#TESTS = $(check_PROGRAMS) + +test_block_SOURCES = \ + test_block.c +test_block_LDADD = \ + $(top_builddir)/src/block/libgnunetblock.la \ + $(top_builddir)/src/util/libgnunetutil.la + diff --git a/src/block/block.c b/src/block/block.c new file mode 100644 index 000000000..24dab7907 --- /dev/null +++ b/src/block/block.c @@ -0,0 +1,230 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet 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, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file block/block.c + * @brief library for data block manipulation + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_signatures.h" +#include "gnunet_block_lib.h" + +/** + * Check if the given KBlock is well-formed. + * + * @param kb the kblock data (or at least "dsize" bytes claiming to be one) + * @param dsize size of "kb" in bytes; check for < sizeof(struct KBlock)! + * @param query where to store the query that this block answers + * @return GNUNET_OK if this is actually a well-formed KBlock + */ +static int +check_kblock (const struct KBlock *kb, + size_t dsize, + GNUNET_HashCode *query) +{ + if (dsize < sizeof (struct KBlock)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (dsize - sizeof (struct KBlock) != + ntohl (kb->purpose.size) + - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) ) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK, + &kb->purpose, + &kb->signature, + &kb->keyspace)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (query != NULL) + GNUNET_CRYPTO_hash (&kb->keyspace, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + query); + return GNUNET_OK; +} + + +/** + * Check if the given NBlock is well-formed. + * + * @param nb the nblock data (or at least "dsize" bytes claiming to be one) + * @param dsize size of "nb" in bytes; check for < sizeof(struct NBlock)! + * @param query where to store the query that this block answers + * @return GNUNET_OK if this is actually a well-formed NBlock + */ +static int +check_nblock (const struct NBlock *nb, + size_t dsize, + GNUNET_HashCode *query) +{ + if (dsize < sizeof (struct NBlock)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (dsize - sizeof (struct NBlock) != + ntohl (nb->ns_purpose.size) + - sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) ) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (dsize != + ntohl (nb->ksk_purpose.size) + sizeof (struct GNUNET_CRYPTO_RsaSignature)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG, + &nb->ksk_purpose, + &nb->ksk_signature, + &nb->keyspace)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK, + &nb->ns_purpose, + &nb->ns_signature, + &nb->subspace)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (query != NULL) + GNUNET_CRYPTO_hash (&nb->keyspace, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + query); + return GNUNET_OK; +} + + +/** + * Check if the given SBlock is well-formed. + * + * @param sb the sblock data (or at least "dsize" bytes claiming to be one) + * @param dsize size of "kb" in bytes; check for < sizeof(struct SBlock)! + * @param query where to store the query that this block answers + * @return GNUNET_OK if this is actually a well-formed SBlock + */ +static int +check_sblock (const struct SBlock *sb, + size_t dsize, + GNUNET_HashCode *query) +{ + if (dsize < sizeof (struct SBlock)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (dsize != + ntohl (sb->purpose.size) + sizeof (struct GNUNET_CRYPTO_RsaSignature)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK, + &sb->purpose, + &sb->signature, + &sb->subspace)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (query != NULL) + *query = sb->identifier; + return GNUNET_OK; +} + + +/** + * Check if the given block is well-formed (and of the given type). + * + * @param type type of the block + * @param block the block data (or at least "size" bytes claiming to be one) + * @param size size of "kb" in bytes; check that it is large enough + * @param query where to store the query that this block answers + * @return GNUNET_OK if this is actually a well-formed block, + * GNUNET_NO if we could not determine the query, + * GNUNET_SYSERR if the block is malformed + */ +int +GNUNET_BLOCK_check_block (enum GNUNET_BLOCK_Type type, + const void *block, + size_t size, + GNUNET_HashCode *query) +{ + /* first, validate! */ + switch (type) + { + case GNUNET_BLOCK_TYPE_DBLOCK: + case GNUNET_BLOCK_TYPE_IBLOCK: + GNUNET_CRYPTO_hash (block, size, query); + break; + case GNUNET_BLOCK_TYPE_KBLOCK: + if (GNUNET_OK != + check_kblock (block, + size, + query)) + return GNUNET_SYSERR; + break; + case GNUNET_BLOCK_TYPE_SBLOCK: + if (GNUNET_OK != + check_sblock (block, + size, + query)) + return GNUNET_SYSERR; + break; + case GNUNET_BLOCK_TYPE_NBLOCK: + if (GNUNET_OK != + check_nblock (block, + size, + query)) + return GNUNET_SYSERR; + return GNUNET_OK; + case GNUNET_BLOCK_TYPE_ONDEMAND: + if (size != sizeof (struct OnDemandBlock)) + return GNUNET_SYSERR; + memset (query, 0, sizeof (GNUNET_HashCode)); + return GNUNET_NO; + default: + /* unknown block type */ + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/* end of block.c */ diff --git a/src/block/test_block b/src/block/test_block new file mode 100755 index 000000000..2b533cc6b --- /dev/null +++ b/src/block/test_block @@ -0,0 +1,148 @@ +#! /bin/sh + +# test_block - temporary wrapper script for .libs/test_block +# Generated by ltmain.sh (GNU libtool) 2.2.6b Debian-2.2.6b-2 +# +# The test_block program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='/bin/sed -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /home/grothoff/svn/gnunet/src/block; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/grothoff/bin:/home/grothoff/private/software/prevent-linux-4.3.0/bin/:/home/grothoff/bin:/usr/local/bin:/usr/bin:/bin:/usr/games; export PATH; gcc -fno-strict-aliasing -Wall -g -O0 -o \$progdir/\$file test_block.o -L/home/grothoff//lib ../../src/block/.libs/libgnunetblock.so ../../src/util/.libs/libgnunetutil.so -lm -ldl -Wl,-rpath -Wl,/home/grothoff/svn/gnunet/src/block/.libs -Wl,-rpath -Wl,/home/grothoff/svn/gnunet/src/util/.libs -Wl,-rpath -Wl,/home/grothoff/lib)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.2.6b' + notinst_deplibs=' ../../src/block/libgnunetblock.la ../../src/util/libgnunetutil.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + ECHO="echo" + file="$0" + # Make sure echo works. + if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then + # Yippee, $ECHO works! + : + else + # Restart under the correct shell, and then maybe $ECHO will work. + exec /bin/sh "$0" --no-reexec ${1+"$@"} + fi + fi + + # Find the directory that this script lives in. + thisdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "X$file" | $Xsed -e 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "X$file" | $Xsed -e 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'` + done + + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "X$thisdir" | $Xsed -e 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'test_block' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + echo "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + echo "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/src/block/test_block.c b/src/block/test_block.c new file mode 100644 index 000000000..b8586982a --- /dev/null +++ b/src/block/test_block.c @@ -0,0 +1,36 @@ +/* + This file is part of GNUnet + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet 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, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +/** + * @file block/test_block.c + * @brief test for block.c + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_block_lib.h" + +#define DEBUG GNUNET_NO + +#define VERBOSE GNUNET_NO + +int +main (int argc, char *argv[]) +{ + return 0; /* testcase passed */ +} diff --git a/src/include/gnunet_block_lib.h b/src/include/gnunet_block_lib.h new file mode 100644 index 000000000..513605eb2 --- /dev/null +++ b/src/include/gnunet_block_lib.h @@ -0,0 +1,249 @@ +/* + This file is part of GNUnet. + (C) 2010 Christian Grothoff (and other contributing authors) + + GNUnet 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, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file include/gnunet_block_lib.h + * @brief library for data block manipulation + * @author Christian Grothoff + */ +#ifndef GNUNET_BLOCK_LIB_H +#define GNUNET_BLOCK_LIB_H + +#include "gnunet_util_lib.h" +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +/** + * Blocks in the datastore and the datacache must have a unique type. + */ +enum GNUNET_BLOCK_Type + { + /** + * Any type of block, used as a wildcard when searching. Should + * never be attached to a specific block. + */ + GNUNET_BLOCK_TYPE_ANY = 0, + + /** + * Data block (leaf) in the CHK tree. + */ + GNUNET_BLOCK_TYPE_DBLOCK = 1, + + /** + * Inner block in the CHK tree. + */ + GNUNET_BLOCK_TYPE_IBLOCK = 2, + + /** + * Type of a block representing a keyword search result. + */ + GNUNET_BLOCK_TYPE_KBLOCK = 3, + + /** + * Type of a block that is used to advertise content in a namespace. + */ + GNUNET_BLOCK_TYPE_SBLOCK = 4, + + /** + * Type of a block representing a block to be encoded on demand from disk. + * Should never appear on the network directly. + */ + GNUNET_BLOCK_TYPE_ONDEMAND = 5, + + /** + * Type of a block that is used to advertise a namespace. + */ + GNUNET_BLOCK_TYPE_NBLOCK = 6 + + }; + + + + + +/** + * @brief keyword block (advertising data under a keyword) + */ +struct KBlock +{ + + /** + * GNUNET_RSA_Signature using RSA-key generated from search keyword. + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * What is being signed and why? + */ + struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; + + /** + * Key generated (!) from the H(keyword) as the seed! + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded keyspace; + + /* 0-terminated URI here */ + + /* variable-size Meta-Data follows here */ + +}; + +/** + * @brief namespace content block (advertising data under an identifier in a namespace) + */ +struct SBlock +{ + + /** + * GNUNET_RSA_Signature using RSA-key of the namespace + */ + struct GNUNET_CRYPTO_RsaSignature signature; + + /** + * What is being signed and why? + */ + struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; + + /** + * Hash of the hash of the human-readable identifier used for + * this entry (the hash of the human-readable identifier is + * used as the key for decryption; the xor of this identifier + * and the hash of the "keyspace" is the datastore-query hash). + */ + GNUNET_HashCode identifier; + + /** + * Public key of the namespace. + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded subspace; + + /* 0-terminated update-identifier here */ + + /* 0-terminated URI here (except for NBlocks) */ + + /* variable-size Meta-Data follows here */ + +}; + + +/** + * @brief namespace advertisement block (advertising root of a namespace) + */ +struct NBlock +{ + + /** + * GNUNET_RSA_Signature using RSA-key generated from search keyword. + */ + struct GNUNET_CRYPTO_RsaSignature ksk_signature; + + /** + * What is being signed and why? + */ + struct GNUNET_CRYPTO_RsaSignaturePurpose ksk_purpose; + + /** + * Key generated (!) from the H(keyword) as the seed! + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded keyspace; + + /** + * GNUNET_RSA_Signature using RSA-key of the namespace + */ + struct GNUNET_CRYPTO_RsaSignature ns_signature; + + /** + * What is being signed and why? + */ + struct GNUNET_CRYPTO_RsaSignaturePurpose ns_purpose; + + /** + * Public key of the namespace. + */ + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded subspace; + + /* from here on, data is encrypted with H(keyword) */ + + /* 0-terminated root identifier here */ + + /* variable-size Meta-Data follows here */ + +}; + + + + +/** + * @brief index block (indexing a DBlock that + * can be obtained directly from reading + * the plaintext file) + */ +struct OnDemandBlock +{ + /** + * Hash code of the entire content of the + * file that was indexed (used to uniquely + * identify the plaintext file). + */ + GNUNET_HashCode file_id; + + /** + * At which offset should we be able to find + * this on-demand encoded block? (in NBO) + */ + uint64_t offset GNUNET_PACKED; + +}; + + +/** + * Check if the given block is well-formed (and of the given type). + * + * @param type type of the block + * @param block the block data (or at least "size" bytes claiming to be one) + * @param size size of "kb" in bytes; check that it is large enough + * @param query where to store the query that this block answers + * @return GNUNET_OK if this is actually a well-formed KBlock + * GNUNET_NO if we could not determine the query, + * GNUNET_SYSERR if the block is malformed + */ +int +GNUNET_BLOCK_check_block (enum GNUNET_BLOCK_Type type, + const void *block, + size_t size, + GNUNET_HashCode *query); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + + +/* ifndef GNUNET_BLOCK_LIB_H */ +#endif +/* end of gnunet_block_lib.h */