From 2da75114d99826c185f82bf46074e8b61e0224a2 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Fri, 28 Oct 2011 22:46:28 +0200 Subject: [PATCH] ipsec attest lists data stored in an attestation database --- .../plugins/imv_attestation/Makefile.am | 4 + src/libimcv/plugins/imv_attestation/attest | 225 +++++++++++++ src/libimcv/plugins/imv_attestation/attest.c | 307 ++++++++++++++++++ .../plugins/imv_attestation/attest_usage.c | 37 +++ .../plugins/imv_attestation/attest_usage.h | 25 ++ 5 files changed, 598 insertions(+) create mode 100755 src/libimcv/plugins/imv_attestation/attest create mode 100644 src/libimcv/plugins/imv_attestation/attest.c create mode 100644 src/libimcv/plugins/imv_attestation/attest_usage.c create mode 100644 src/libimcv/plugins/imv_attestation/attest_usage.h diff --git a/src/libimcv/plugins/imv_attestation/Makefile.am b/src/libimcv/plugins/imv_attestation/Makefile.am index c6eb46d65..59ce5ffa7 100644 --- a/src/libimcv/plugins/imv_attestation/Makefile.am +++ b/src/libimcv/plugins/imv_attestation/Makefile.am @@ -17,3 +17,7 @@ imv_attestation_la_SOURCES = imv_attestation.c \ imv_attestation_la_LDFLAGS = -module -avoid-version +ipsec_PROGRAMS = attest +attest_SOURCES = attest.c attest_usage.h attest_usage.c +attest_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la +attest.o : $(top_builddir)/config.status diff --git a/src/libimcv/plugins/imv_attestation/attest b/src/libimcv/plugins/imv_attestation/attest new file mode 100755 index 000000000..5f5393eff --- /dev/null +++ b/src/libimcv/plugins/imv_attestation/attest @@ -0,0 +1,225 @@ +#! /bin/bash + +# attest - temporary wrapper script for .libs/attest +# Generated by libtool (GNU libtool) 2.4 Debian-2.4-2ubuntu1 +# +# The attest 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. +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/andi/pts-binding/src/libimcv/plugins/imv_attestation; { 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/andi/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games; export PATH; gcc -rdynamic -g -O2 -Wall -Wno-format -Wno-pointer-sign -o \$progdir/\$file attest.o attest_usage.o ../../../../src/libstrongswan/.libs/libstrongswan.so -Wl,-rpath -Wl,/home/andi/pts-binding/src/libstrongswan/.libs -Wl,-rpath -Wl,/usr/lib/ipsec)" + +# 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.4' + notinst_deplibs=' ../../../../src/libstrongswan/libstrongswan.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "attest:attest:${LINENO}: libtool wrapper (GNU libtool) 2.4 Debian-2.4-2ubuntu1" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "attest:attest:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "attest:attest:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /bin/sed '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 "$file" | /bin/sed '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 "$file" | /bin/sed '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 "$thisdir" | /bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'attest' + 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 + printf %s\n "$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. + func_exec_program ${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/libimcv/plugins/imv_attestation/attest.c b/src/libimcv/plugins/imv_attestation/attest.c new file mode 100644 index 000000000..f2b2eb546 --- /dev/null +++ b/src/libimcv/plugins/imv_attestation/attest.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program 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. See . + * + * This program 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include +#include + +#include "attest_usage.h" + +/** + * global database handle + */ +database_t *db; + +/** + * forward declarations + */ +static void do_args(int argc, char *argv[]); + +/** + * ipsec attest --files - show files + */ +static void list_files(char *product, int pid) +{ + enumerator_t *e; + char *file; + bool select = TRUE; + int fid, is_dir, count = 0; + + if (pid) + { + e = db->query(db, + "SELECT name FROM products WHERE id = ?", + DB_INT, pid, DB_TEXT); + if (e) + { + if (e->enumerate(e, &product)) + { + product = strdup(product); + e->destroy(e); + } + else + { + printf("no product found with pid %d\n", pid); + e->destroy(e); + return; + } + } + e = db->query(db, + "SELECT f.id, f.type, f.path FROM files AS f " + "JOIN product_file AS pf ON f.id = pf.file " + "JOIN products AS p ON p.id = pf.product " + "WHERE p.id = ? ORDER BY f.path", + DB_INT, pid, DB_INT, DB_INT, DB_TEXT); + } + else if (!product || *product == '\0') + { + select = FALSE; + e = db->query(db, + "SELECT id, type, path FROM files " + "ORDER BY path", + DB_INT, DB_INT, DB_TEXT); + } + else + { + e = db->query(db, + "SELECT f.id, f.type, f.path FROM files AS f " + "JOIN product_file AS pf ON f.id = pf.file " + "JOIN products AS p ON p.id = pf.product " + "WHERE p.name = ? ORDER BY f.path", + DB_TEXT, product, DB_INT, DB_INT, DB_TEXT); + } + if (e) + { + while (e->enumerate(e, &fid, &is_dir, &file)) + { + printf("%3d: %s %s\n", fid, is_dir ? "d":"f", file); + count++; + } + e->destroy(e); + + printf("%d file%s found", count, (count == 1) ? "" : "s"); + if (select) + { + printf(" for product '%s'", product); + } + printf("\n"); + if (pid) + { + free(product); + } + } +} + +/** + * ipsec attest --products - show products + */ +static void list_products(char *file, int fid) +{ + enumerator_t *e; + char *product; + bool select = TRUE; + int pid, count = 0; + + if (fid) + { + e = db->query(db, + "SELECT path FROM files WHERE id = ?", + DB_INT, fid, DB_TEXT); + if (e) + { + if (e->enumerate(e, &file)) + { + file = strdup(file); + e->destroy(e); + } + else + { + printf("no file found with fid %d\n", fid); + e->destroy(e); + return; + } + } + e = db->query(db, + "SELECT p.id, p.name FROM products AS p " + "JOIN product_file AS pf ON p.id = pf.product " + "JOIN files AS f ON f.id = pf.file " + "WHERE f.id = ? ORDER BY p.name", + DB_INT, fid, DB_INT, DB_TEXT); + } + else if (!file || *file == '\0') + { + select = FALSE; + e = db->query(db, "SELECT id, name FROM products " + "ORDER BY name", + DB_INT, DB_TEXT); + } + else + { + e = db->query(db, + "SELECT p.id, p.name FROM products AS p " + "JOIN product_file AS pf ON p.id = pf.product " + "JOIN files AS f ON f.id = pf.file " + "WHERE f.path = ? ORDER BY p.name", + DB_TEXT, file, DB_INT, DB_TEXT); + } + if (e) + { + while (e->enumerate(e, &pid, &product)) + { + printf("%3d: %s\n", pid, product); + count++; + } + e->destroy(e); + + printf("%d product%s found", count, (count == 1) ? "" : "s"); + if (select) + { + printf(" for file '%s'", file); + } + printf("\n"); + if (fid) + { + free(file); + } + } +} + +/** + * atexit handler to close db on shutdown + */ +static void cleanup(void) +{ + db->destroy(db); +} + +static void do_args(int argc, char *argv[]) +{ + char *product = NULL, *file = NULL; + int fid = 0, pid = 0; + + enum { + OP_UNDEF, + OP_USAGE, + OP_PRODUCTS, + OP_FILES, + } operation = OP_UNDEF; + + /* reinit getopt state */ + optind = 0; + + while (TRUE) + { + int c; + + struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + { "files", no_argument, NULL, 'f' }, + { "products", no_argument, NULL, 'p' }, + { "file", required_argument, NULL, 'F' }, + { "product", required_argument, NULL, 'P' }, + { "fid", required_argument, NULL, '1' }, + { "pid", required_argument, NULL, '2' }, + { 0,0,0,0 } + }; + + c = getopt_long(argc, argv, "", long_opts, NULL); + switch (c) + { + case EOF: + break; + case 'h': + operation = OP_USAGE; + break; + case 'f': + operation = OP_FILES; + continue; + case 'p': + operation = OP_PRODUCTS; + continue; + case 'F': + file = optarg; + continue; + case 'P': + product = optarg; + continue; + case '1': + fid = atoi(optarg); + continue; + case '2': + pid = atoi(optarg); + continue; + } + break; + } + + switch (operation) + { + case OP_USAGE: + usage(); + break; + case OP_PRODUCTS: + list_products(file, fid); + break; + case OP_FILES: + list_files(product, pid); + break; + default: + usage(); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char *argv[]) +{ + char *uri; + + atexit(library_deinit); + + /* initialize library */ + if (!library_init(NULL)) + { + exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); + } + if (!lib->plugins->load(lib->plugins, NULL, + lib->settings->get_str(lib->settings, "attest.load", "sqlite"))) + { + exit(SS_RC_INITIALIZATION_FAILED); + } + + uri = lib->settings->get_str(lib->settings, "attest.database", NULL); + if (!uri) + { + fprintf(stderr, "database URI attest.database not set.\n"); + exit(SS_RC_INITIALIZATION_FAILED); + } + db = lib->db->create(lib->db, uri); + if (!db) + { + fprintf(stderr, "opening database failed.\n"); + exit(SS_RC_INITIALIZATION_FAILED); + } + atexit(cleanup); + + do_args(argc, argv); + + exit(EXIT_SUCCESS); +} + diff --git a/src/libimcv/plugins/imv_attestation/attest_usage.c b/src/libimcv/plugins/imv_attestation/attest_usage.c new file mode 100644 index 000000000..9775c954c --- /dev/null +++ b/src/libimcv/plugins/imv_attestation/attest_usage.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Martin Willi + * Copyright (C) 2009-2010 Andreas Steffen + * Hochschule fuer Technik Rapperswil + * + * This program 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. See . + * + * This program 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. + */ + +#include + +/** + * print attest usage info + */ +void usage(void) +{ + printf("\ +Usage:\n\ + ipsec attest --files|--products [options]\n\ + \n\ + ipsec attest --files [--product |--pid ]\n\ + Show a list of supported files with a sofware product name or\n\ + its primary key as a selector.\n\ + \n\ + ipsec attest --products [--file |--fid ]\n\ + Show a list of software products with a file path or\n\ + its primary key as a selector.\n\ + \n"); +} + diff --git a/src/libimcv/plugins/imv_attestation/attest_usage.h b/src/libimcv/plugins/imv_attestation/attest_usage.h new file mode 100644 index 000000000..bce801e9d --- /dev/null +++ b/src/libimcv/plugins/imv_attestation/attest_usage.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program 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. See . + * + * This program 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. + */ + +#ifndef ATTEST_USAGE_H_ +#define ATTEST_USAGE_H_ + +/** + * print attest usage info + */ +void usage(void); + + +#endif /* ATTEST_USAGE_H_ */