diff --git a/g10/Makefile.am b/g10/Makefile.am index 0c53eab97..421870c5e 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -19,9 +19,9 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST = options.skel distsigkey.gpg ChangeLog-2011 gpg-w32info.rc \ - gpg.w32-manifest.in + gpg.w32-manifest.in test.c -AM_CPPFLAGS = -I$(top_srcdir)/common +AM_CPPFLAGS = -I$(top_srcdir)/common -DSOURCE_DIR="\"$(srcdir)\"" include $(top_srcdir)/am/cmacros.am @@ -150,9 +150,12 @@ gpgv2_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) \ gpgv2_LDFLAGS = $(extra_bin_ldflags) t_common_ldadd = -module_tests = t-rmd160 +module_tests = t-rmd160 t-keydb t_rmd160_SOURCES = t-rmd160.c rmd160.c t_rmd160_LDADD = $(t_common_ldadd) +t_keydb_SOURCES = t-keydb.c test-stubs.c $(common_source) +t_keydb_LDADD = $(LDADD) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBICONV) $(t_common_ldadd) $(PROGRAMS): $(needed_libs) ../common/libgpgrl.a diff --git a/g10/t-keydb-keyring.kbx b/g10/t-keydb-keyring.kbx new file mode 100644 index 000000000..a1d3af073 Binary files /dev/null and b/g10/t-keydb-keyring.kbx differ diff --git a/g10/t-keydb.c b/g10/t-keydb.c new file mode 100644 index 000000000..0f176431c --- /dev/null +++ b/g10/t-keydb.c @@ -0,0 +1,87 @@ +/* t-keydb.c - Tests for keydb.c. + * Copyright (C) 2015 g10 Code GmbH + * + * 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 3 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, see . + */ + +#include "test.c" + +#include "keydb.h" + +static void +do_test (int argc, char *argv[]) +{ + int rc; + KEYDB_HANDLE hd1, hd2; + KEYDB_SEARCH_DESC desc1, desc2; + KBNODE kb1, kb2; + char *uid1; + char *uid2; + + (void) argc; + (void) argv; + + rc = keydb_add_resource (SOURCE_DIR "/t-keydb-keyring.kbx", 0); + if (rc) + ABORT ("Failed to open keyring."); + + hd1 = keydb_new (); + hd2 = keydb_new (); + + rc = classify_user_id ("2689 5E25 E844 6D44 A26D 8FAF 2F79 98F3 DBFC 6AD9", + &desc1, 0); + if (rc) + ABORT ("Failed to convert fingerprint for DBFC6AD9"); + + rc = keydb_search (hd1, &desc1, 1, NULL); + if (rc) + ABORT ("Failed to lookup key associated with DBFC6AD9"); + + + classify_user_id ("8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367", + &desc2, 0); + if (rc) + ABORT ("Failed to convert fingerprint for 1E42B367"); + + rc = keydb_search (hd2, &desc2, 1, NULL); + if (rc) + ABORT ("Failed to lookup key associated with 1E42B367"); + + rc = keydb_get_keyblock (hd2, &kb2); + if (rc) + ABORT ("Failed to get keyblock for 1E42B367"); + + rc = keydb_get_keyblock (hd1, &kb1); + if (rc) + ABORT ("Failed to get keyblock for DBFC6AD9"); + + while (kb1 && kb1->pkt->pkttype != PKT_USER_ID) + kb1 = kb1->next; + if (! kb1) + ABORT ("DBFC6AD9 has no user id packet"); + uid1 = kb1->pkt->pkt.user_id->name; + + while (kb2 && kb2->pkt->pkttype != PKT_USER_ID) + kb2 = kb2->next; + if (! kb2) + ABORT ("1E42B367 has no user id packet"); + uid2 = kb2->pkt->pkt.user_id->name; + + printf ("user id for DBFC6AD9: %s\n", uid1); + printf ("user id for 1E42B367: %s\n", uid2); + + TEST_P ("cache consistency", strcmp (uid1, uid2) != 0); +} diff --git a/g10/test-stubs.c b/g10/test-stubs.c new file mode 100644 index 000000000..c6f6d68e9 --- /dev/null +++ b/g10/test-stubs.c @@ -0,0 +1,413 @@ +/* test-stubs.c - The GnuPG signature verify utility + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, + * 2008, 2009, 2012 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define INCLUDED_BY_MAIN_MODULE 1 +#include "gpg.h" +#include "util.h" +#include "packet.h" +#include "iobuf.h" +#include "main.h" +#include "options.h" +#include "keydb.h" +#include "trustdb.h" +#include "filter.h" +#include "ttyio.h" +#include "i18n.h" +#include "sysutils.h" +#include "status.h" +#include "call-agent.h" + +int g10_errors_seen; + + +void +g10_exit( int rc ) +{ + rc = rc? rc : log_get_errorcount(0)? 2 : g10_errors_seen? 1 : 0; + exit(rc ); +} + + +/* Stub: + * We have to override the trustcheck from pkclist.c becuase + * this utility assumes that all keys in the keyring are trustworthy + */ +int +check_signatures_trust( PKT_signature *sig ) +{ + (void)sig; + return 0; +} + +void +read_trust_options(byte *trust_model, ulong *created, ulong *nextcheck, + byte *marginals, byte *completes, byte *cert_depth, + byte *min_cert_level) +{ + (void)trust_model; + (void)created; + (void)nextcheck; + (void)marginals; + (void)completes; + (void)cert_depth; + (void)min_cert_level; +} + +/* Stub: + * We don't have the trustdb , so we have to provide some stub functions + * instead + */ + +int +cache_disabled_value(PKT_public_key *pk) +{ + (void)pk; + return 0; +} + +void +check_trustdb_stale(void) +{ +} + +int +get_validity_info (PKT_public_key *pk, PKT_user_id *uid) +{ + (void)pk; + (void)uid; + return '?'; +} + +unsigned int +get_validity (PKT_public_key *pk, PKT_user_id *uid) +{ + (void)pk; + (void)uid; + return 0; +} + +const char * +trust_value_to_string (unsigned int value) +{ + (void)value; + return "err"; +} + +const char * +uid_trust_string_fixed (PKT_public_key *key, PKT_user_id *uid) +{ + (void)key; + (void)uid; + return "err"; +} + +int +get_ownertrust_info (PKT_public_key *pk) +{ + (void)pk; + return '?'; +} + +unsigned int +get_ownertrust (PKT_public_key *pk) +{ + (void)pk; + return TRUST_UNKNOWN; +} + + +/* Stubs: + * Because we only work with trusted keys, it does not make sense to + * get them from a keyserver + */ + +struct keyserver_spec * +keyserver_match (struct keyserver_spec *spec) +{ + (void)spec; + return NULL; +} + +int +keyserver_import_keyid (u32 *keyid, void *dummy) +{ + (void)keyid; + (void)dummy; + return -1; +} + +int +keyserver_import_cert (const char *name) +{ + (void)name; + return -1; +} + +int +keyserver_import_pka (const char *name,unsigned char *fpr) +{ + (void)name; + (void)fpr; + return -1; +} + +int +keyserver_import_name (const char *name,struct keyserver_spec *spec) +{ + (void)name; + (void)spec; + return -1; +} + +int +keyserver_import_ldap (const char *name) +{ + (void)name; + return -1; +} + +/* Stub: + * No encryption here but mainproc links to these functions. + */ +gpg_error_t +get_session_key (PKT_pubkey_enc *k, DEK *dek) +{ + (void)k; + (void)dek; + return GPG_ERR_GENERAL; +} + +/* Stub: */ +gpg_error_t +get_override_session_key (DEK *dek, const char *string) +{ + (void)dek; + (void)string; + return GPG_ERR_GENERAL; +} + +/* Stub: */ +int +decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) +{ + (void)ctrl; + (void)procctx; + (void)ed; + (void)dek; + return GPG_ERR_GENERAL; +} + + +/* Stub: + * No interactive commands, so we don't need the helptexts + */ +void +display_online_help (const char *keyword) +{ + (void)keyword; +} + +/* Stub: + * We don't use secret keys, but getkey.c links to this + */ +int +check_secret_key (PKT_public_key *pk, int n) +{ + (void)pk; + (void)n; + return GPG_ERR_GENERAL; +} + +/* Stub: + * No secret key, so no passphrase needed + */ +DEK * +passphrase_to_dek (u32 *keyid, int pubkey_algo, + int cipher_algo, STRING2KEY *s2k, int mode, + const char *tmp, int *canceled) +{ + (void)keyid; + (void)pubkey_algo; + (void)cipher_algo; + (void)s2k; + (void)mode; + (void)tmp; + + if (canceled) + *canceled = 0; + return NULL; +} + +void +passphrase_clear_cache (u32 *keyid, const char *cacheid, int algo) +{ + (void)keyid; + (void)cacheid; + (void)algo; +} + +struct keyserver_spec * +parse_preferred_keyserver(PKT_signature *sig) +{ + (void)sig; + return NULL; +} + +struct keyserver_spec * +parse_keyserver_uri (const char *uri, int require_scheme, + const char *configname, unsigned int configlineno) +{ + (void)uri; + (void)require_scheme; + (void)configname; + (void)configlineno; + return NULL; +} + +void +free_keyserver_spec (struct keyserver_spec *keyserver) +{ + (void)keyserver; +} + +/* Stubs to avoid linking to photoid.c */ +void +show_photos (const struct user_attribute *attrs, int count, PKT_public_key *pk) +{ + (void)attrs; + (void)count; + (void)pk; +} + +int +parse_image_header (const struct user_attribute *attr, byte *type, u32 *len) +{ + (void)attr; + (void)type; + (void)len; + return 0; +} + +char * +image_type_to_string (byte type, int string) +{ + (void)type; + (void)string; + return NULL; +} + +#ifdef ENABLE_CARD_SUPPORT +int +agent_scd_getattr (const char *name, struct agent_card_info_s *info) +{ + (void)name; + (void)info; + return 0; +} +#endif /* ENABLE_CARD_SUPPORT */ + +/* We do not do any locking, so use these stubs here */ +void +dotlock_disable (void) +{ +} + +dotlock_t +dotlock_create (const char *file_to_lock, unsigned int flags) +{ + (void)file_to_lock; + (void)flags; + return NULL; +} + +void +dotlock_destroy (dotlock_t h) +{ + (void)h; +} + +int +dotlock_take (dotlock_t h, long timeout) +{ + (void)h; + (void)timeout; + return 0; +} + +int +dotlock_release (dotlock_t h) +{ + (void)h; + return 0; +} + +void +dotlock_remove_lockfiles (void) +{ +} + +gpg_error_t +agent_probe_secret_key (ctrl_t ctrl, PKT_public_key *pk) +{ + (void)ctrl; + (void)pk; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +agent_probe_any_secret_key (ctrl_t ctrl, kbnode_t keyblock) +{ + (void)ctrl; + (void)keyblock; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno) +{ + (void)ctrl; + (void)hexkeygrip; + *r_serialno = NULL; + return gpg_error (GPG_ERR_NO_SECKEY); +} + +gpg_error_t +gpg_dirmngr_get_pka (ctrl_t ctrl, const char *userid, + unsigned char **r_fpr, size_t *r_fprlen, + char **r_url) +{ + (void)ctrl; + (void)userid; + if (r_fpr) + *r_fpr = NULL; + if (r_fprlen) + *r_fprlen = 0; + if (r_url) + *r_url = NULL; + return gpg_error (GPG_ERR_NOT_FOUND); +} diff --git a/g10/test.c b/g10/test.c new file mode 100644 index 000000000..6910f95ad --- /dev/null +++ b/g10/test.c @@ -0,0 +1,141 @@ +/* test.c - Infrastructure for unit tests. + * Copyright (C) 2015 g10 Code GmbH + * + * 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 3 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, see . + */ + +#include +#include "gpg.h" + +/* A unit test consists of one or more tests. Tests can be broken + into groups and each group can consist of one or more tests. */ + +/* The number of test groups. */ +static int test_groups; +/* The current test group. */ +static char *test_group; + +/* Whether there was already a failure in the current test group. */ +static int current_test_group_failed; +/* The number of test groups with a failure. */ +static int test_groups_failed; + +/* The total number of tests. */ +static int tests; +/* The total number of tests that failed. */ +static int tests_failed; + +#define TEST_GROUP(description) \ + do { \ + test_group = (description); \ + test_groups ++; \ + current_test_group_failed = 0; \ + } while (0) + +#define STRINGIFY2(x) #x +#define STRINGIFY(x) STRINGIFY2(x) + +/* Execute a test. */ +#define TEST(description, test, expected) \ + do { \ + int test_result; \ + int expected_result; \ + \ + tests ++; \ + \ + printf ("%d. Checking %s...", \ + tests, (description) ?: ""); \ + fflush (stdout); \ + \ + test_result = (test); \ + expected_result = (expected); \ + \ + if (test_result == expected_result) \ + { \ + printf (" ok.\n"); \ + } \ + else \ + { \ + printf (" failed.\n"); \ + printf (" %s == %s failed.\n", \ + STRINGIFY(test), \ + STRINGIFY(expected)); \ + tests_failed ++; \ + if (! current_test_group_failed) \ + { \ + current_test_group_failed = 1; \ + test_groups_failed ++; \ + } \ + } \ + } while (0) + +/* Test that a condition evaluates to true. */ +#define TEST_P(description, test) \ + TEST(description, !!(test), 1) + +/* Like CHECK, but if the test fails, abort the program. */ +#define ASSERT(description, test, expected) \ + do { \ + int tests_failed_pre = tests_failed; \ + CHECK(description, test, expected); \ + if (tests_failed_pre != tests_failed) \ + exit (1); \ + } while (0) + +/* Call this if something went wrong. */ +#define ABORT(message) \ + do { \ + printf ("aborting..."); \ + if (message) \ + printf (" %s\n", (message)); \ + \ + exit(1); \ + } while (0) + +/* You need to fill this function in. */ +static void do_test (int argc, char *argv[]); + +static void +print_results (void) +{ + if (tests_failed == 0) + { + printf ("All %d tests passed.\n", tests); + exit (0); + } + else + { + printf ("%d of %d tests failed", + tests_failed, tests); + if (test_groups > 1) + printf (" (%d of %d groups)", + test_groups_failed, test_groups); + printf ("\n"); + + exit (1); + } +} + +int +main (int argc, char *argv[]) +{ + (void) test_group; + + do_test (argc, argv); + atexit (print_results); + + return tests_failed == 0; +}