--- /dev/null +++ b/client/checkfile.c @@ -0,0 +1,141 @@ +/* + * Test file object checksum against a file on the system + * + * Written by Bill MacAllister + * Copyright 2020 Dropbox, Inc. + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* Given a string and its length return a checksum for the string. + */ +char *checkfile_str2md5(const char *str, int length) { + int n; + MD5_CTX c; + unsigned char digest[16]; + char *out = (char*)malloc(33); + + MD5_Init(&c); + + while (length > 0) { + if (length > 512) { + MD5_Update(&c, str, 512); + } else { + MD5_Update(&c, str, length); + } + length -= 512; + str += 512; + } + + MD5_Final(digest, &c); + + for (n = 0; n < 16; ++n) { + snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]); + } + + return out; +} + +/* + * Read all of a file into memory and return the contents in newly allocated + * memory. Returns the size of the file contents in the second argument if + * it's not NULL. Dies on any failure. + */ +void * +checkfile_read_file(const char *name, size_t *length) +{ + char *contents; + size_t size, offset; + int fd; + struct stat st; + ssize_t status; + + fd = open(name, O_RDONLY); + if (fd < 0) + return NULL; + if (fstat(fd, &st) < 0) + return NULL; + size = st.st_size; + contents = xmalloc(size); + + offset = 0; + do { + if (offset >= size - 1) { + size += BUFSIZ; + contents = xrealloc(contents, size); + } + do { + status = read(fd, contents + offset, size - offset - 1); + } while (status == -1 && errno == EINTR); + if (status < 0) + sysdie("cannot read from file"); + offset += status; + } while (status > 0); + close(fd); + if (length != NULL) + *length = offset; + return contents; +} + +/* + * Given a remctl object, the command prefix, object type, and object name, + * and a file calculate the checksum of the file, get the checksum of + * the wallet object, and compare them. Returns 0 if the checksums + * match and an exit status on if the don't match. + */ +int +checkfile(struct remctl *r, const char *prefix, const char *type, + const char *name, const char *file) +{ + const char *command[5]; + char *file_data = NULL; + char *file_checksum = NULL; + size_t count, length; + char *wallet_checksum = NULL; + size_t wallet_length = 0; + int status; + + /* Check to see if the file exists. It not return mismatch status */ + file_data = checkfile_read_file(file, &length); + if (file_data == NULL) { + return 1; + } + + command[0] = prefix; + command[1] = "checksum"; + command[2] = type; + command[3] = name; + command[4] = NULL; + status = run_command(r, command, &wallet_checksum, &wallet_length); + if (status != 0) { + return status; + } + + /* If the wallet object is empty or NULL return mismatch and let the + * subsequent call to file handle the error condition of an empty + * file object. + */ + if ((wallet_length == 0) || (wallet_checksum == NULL)) { + return 1; + } + + file_checksum = checkfile_str2md5(file_data, length); + status = strncmp(file_checksum, wallet_checksum, wallet_length); + + return status; +} --- a/client/wallet.c +++ b/client/wallet.c @@ -124,9 +124,18 @@ main(int argc, char *argv[]) usage(1); /* -f is only supported for get and store and -S with get keytab. */ - if (file != NULL) - if (strcmp(argv[0], "get") != 0 && strcmp(argv[0], "store") != 0) + if (file != NULL) { + if (strcmp(argv[0], "get") != 0 && + strcmp(argv[0], "store") != 0 && + strcmp(argv[0], "checkfile") != 0) + { die("-f only supported for get and store"); + } + } else { + if (strcmp(argv[0], "checkfile") == 0) + die("-f is required by checkfile"); + } + if (srvtab != NULL) { if (strcmp(argv[0], "get") != 0 || strcmp(argv[1], "keytab") != 0) die("-S only supported for get keytab"); @@ -172,6 +181,14 @@ main(int argc, char *argv[]) if (argc > 2) die("too many arguments"); status = rekey_keytab(r, ctx, options.type, argv[1]); + } else if (strcmp(argv[0], "checkfile") == 0) { + if (argc > 3) + die("too many arguments"); + if (strcmp(argv[1], "keytab") == 0) + die("checkfile command is not valid for keytabs"); + status = checkfile(r, options.type, argv[1], argv[2], file); + if (status != 0) + status = get_file(r, options.type, argv[1], argv[2], file); } else { count = argc + 1; if (strcmp(argv[0], "store") == 0) { --- a/client/wallet.pod +++ b/client/wallet.pod @@ -263,7 +263,14 @@ already exist. Check whether an object of type and name already exists. If it does, prints C; if not, prints C. -=item checksum +=item checkfile + +Preforms a get command only if the wallet object checksum differs from +the checksum of the file specified. The -f switch must be specified. +This command is not valid for keytabs and the wallet object must have +been stored. + +=item checksum Returns the checksum for file objects. --- a/client/internal.h +++ b/client/internal.h @@ -97,6 +97,15 @@ int get_file(struct remctl *, const char const char *name, const char *file); /* + * Given a remctl object, the command prefix, object type, and object name, + * and a file calculate the checksum of the file, get the checksum of + * the wallet object, and compare them. Returns 0 if the checksums + * match and an exit status on if the don't match. + */ +int checkfile(struct remctl *r, const char *prefix, const char *type, + const char *name, const char *file); + +/* * Given a remctl object, the Kerberos context, the type for the wallet * interface, the name of a keytab object, and a file name, call the correct * wallet commands to download a keytab and write it to that file. If srvtab --- a/Makefile.am +++ b/Makefile.am @@ -20,119 +20,119 @@ WALLET_PERL_FLAGS ?= # added to EXTRA_DIST and so that they can be copied over properly for # builddir != srcdir builds. PERL_FILES = perl/Build.PL perl/MANIFEST perl/MANIFEST.SKIP perl/create-ddl \ - perl/lib/Wallet/ACL.pm perl/lib/Wallet/ACL/Base.pm \ - perl/lib/Wallet/ACL/External.pm perl/lib/Wallet/ACL/Krb5.pm \ - perl/lib/Wallet/ACL/Krb5/Regex.pm \ - perl/lib/Wallet/ACL/LDAP/Attribute.pm \ - perl/lib/Wallet/ACL/LDAP/Attribute/Root.pm \ - perl/lib/Wallet/ACL/NetDB.pm perl/lib/Wallet/ACL/Nested.pm \ - perl/lib/Wallet/ACL/NetDB/Root.pm perl/lib/Wallet/Admin.pm \ - perl/lib/Wallet/Config.pm perl/lib/Wallet/Database.pm \ - perl/lib/Wallet/Kadmin.pm perl/lib/Wallet/Kadmin/AD.pm \ - perl/lib/Wallet/Kadmin/Heimdal.pm perl/lib/Wallet/Kadmin/MIT.pm \ - perl/lib/Wallet/Object/Base.pm perl/lib/Wallet/Object/Duo.pm \ - perl/lib/Wallet/Object/File.pm perl/lib/Wallet/Object/Keytab.pm \ - perl/lib/Wallet/Object/Password.pm \ - perl/lib/Wallet/Object/WAKeyring.pm \ - perl/lib/Wallet/Policy/Stanford.pm perl/lib/Wallet/Report.pm \ - perl/lib/Wallet/Schema.pm perl/lib/Wallet/Server.pm \ - perl/lib/Wallet/Schema/Result/Acl.pm \ - perl/lib/Wallet/Schema/Result/AclEntry.pm \ - perl/lib/Wallet/Schema/Result/AclHistory.pm \ - perl/lib/Wallet/Schema/Result/AclScheme.pm \ - perl/lib/Wallet/Schema/Result/Duo.pm \ - perl/lib/Wallet/Schema/Result/Enctype.pm \ - perl/lib/Wallet/Schema/Result/Flag.pm \ - perl/lib/Wallet/Schema/Result/KeytabEnctype.pm \ - perl/lib/Wallet/Schema/Result/KeytabSync.pm \ - perl/lib/Wallet/Schema/Result/Object.pm \ - perl/lib/Wallet/Schema/Result/ObjectHistory.pm \ - perl/lib/Wallet/Schema/Result/SyncTarget.pm \ - perl/lib/Wallet/Schema/Result/Type.pm \ - perl/sql/Wallet-Schema-0.07-0.08-MySQL.sql \ - perl/sql/Wallet-Schema-0.07-0.08-SQLite.sql \ - perl/sql/Wallet-Schema-0.07-MySQL.sql \ - perl/sql/Wallet-Schema-0.07-SQLite.sql \ - perl/sql/Wallet-Schema-0.08-0.09-MySQL.sql \ - perl/sql/Wallet-Schema-0.08-0.09-PostgreSQL.sql \ - perl/sql/Wallet-Schema-0.08-0.09-SQLite.sql \ - perl/sql/Wallet-Schema-0.08-MySQL.sql \ - perl/sql/Wallet-Schema-0.08-PostgreSQL.sql \ - perl/sql/Wallet-Schema-0.08-SQLite.sql \ - perl/sql/Wallet-Schema-0.09-MySQL.sql \ - perl/sql/Wallet-Schema-0.09-PostgreSQL.sql \ - perl/sql/Wallet-Schema-0.09-SQLite.sql \ - perl/sql/Wallet-Schema-0.09-0.10-MySQL.sql \ - perl/sql/Wallet-Schema-0.09-0.10-PostgreSQL.sql \ - perl/sql/Wallet-Schema-0.09-0.10-SQLite.sql \ - perl/sql/Wallet-Schema-0.10-MySQL.sql \ - perl/sql/Wallet-Schema-0.10-PostgreSQL.sql \ - perl/sql/Wallet-Schema-0.10-SQLite.sql \ - perl/sql/wallet-1.3-update-duo.sql perl/t/data/README \ - perl/t/data/acl-command perl/t/data/duo/integration.json \ - perl/t/data/duo/integration-ldap.json \ - perl/t/data/duo/integration-radius.json \ - perl/t/data/duo/integration-rdp.json perl/t/data/duo/keys.json \ - perl/t/data/keytab-fake perl/t/data/keytab.conf \ + perl/lib/Wallet/ACL.pm perl/lib/Wallet/ACL/Base.pm \ + perl/lib/Wallet/ACL/External.pm perl/lib/Wallet/ACL/Krb5.pm \ + perl/lib/Wallet/ACL/Krb5/Regex.pm \ + perl/lib/Wallet/ACL/LDAP/Attribute.pm \ + perl/lib/Wallet/ACL/LDAP/Attribute/Root.pm \ + perl/lib/Wallet/ACL/NetDB.pm perl/lib/Wallet/ACL/Nested.pm \ + perl/lib/Wallet/ACL/NetDB/Root.pm perl/lib/Wallet/Admin.pm \ + perl/lib/Wallet/Config.pm perl/lib/Wallet/Database.pm \ + perl/lib/Wallet/Kadmin.pm perl/lib/Wallet/Kadmin/AD.pm \ + perl/lib/Wallet/Kadmin/Heimdal.pm perl/lib/Wallet/Kadmin/MIT.pm \ + perl/lib/Wallet/Object/Base.pm perl/lib/Wallet/Object/Duo.pm \ + perl/lib/Wallet/Object/File.pm perl/lib/Wallet/Object/Keytab.pm \ + perl/lib/Wallet/Object/Password.pm \ + perl/lib/Wallet/Object/WAKeyring.pm \ + perl/lib/Wallet/Policy/Stanford.pm perl/lib/Wallet/Report.pm \ + perl/lib/Wallet/Schema.pm perl/lib/Wallet/Server.pm \ + perl/lib/Wallet/Schema/Result/Acl.pm \ + perl/lib/Wallet/Schema/Result/AclEntry.pm \ + perl/lib/Wallet/Schema/Result/AclHistory.pm \ + perl/lib/Wallet/Schema/Result/AclScheme.pm \ + perl/lib/Wallet/Schema/Result/Duo.pm \ + perl/lib/Wallet/Schema/Result/Enctype.pm \ + perl/lib/Wallet/Schema/Result/Flag.pm \ + perl/lib/Wallet/Schema/Result/KeytabEnctype.pm \ + perl/lib/Wallet/Schema/Result/KeytabSync.pm \ + perl/lib/Wallet/Schema/Result/Object.pm \ + perl/lib/Wallet/Schema/Result/ObjectHistory.pm \ + perl/lib/Wallet/Schema/Result/SyncTarget.pm \ + perl/lib/Wallet/Schema/Result/Type.pm \ + perl/sql/Wallet-Schema-0.07-0.08-MySQL.sql \ + perl/sql/Wallet-Schema-0.07-0.08-SQLite.sql \ + perl/sql/Wallet-Schema-0.07-MySQL.sql \ + perl/sql/Wallet-Schema-0.07-SQLite.sql \ + perl/sql/Wallet-Schema-0.08-0.09-MySQL.sql \ + perl/sql/Wallet-Schema-0.08-0.09-PostgreSQL.sql \ + perl/sql/Wallet-Schema-0.08-0.09-SQLite.sql \ + perl/sql/Wallet-Schema-0.08-MySQL.sql \ + perl/sql/Wallet-Schema-0.08-PostgreSQL.sql \ + perl/sql/Wallet-Schema-0.08-SQLite.sql \ + perl/sql/Wallet-Schema-0.09-MySQL.sql \ + perl/sql/Wallet-Schema-0.09-PostgreSQL.sql \ + perl/sql/Wallet-Schema-0.09-SQLite.sql \ + perl/sql/Wallet-Schema-0.09-0.10-MySQL.sql \ + perl/sql/Wallet-Schema-0.09-0.10-PostgreSQL.sql \ + perl/sql/Wallet-Schema-0.09-0.10-SQLite.sql \ + perl/sql/Wallet-Schema-0.10-MySQL.sql \ + perl/sql/Wallet-Schema-0.10-PostgreSQL.sql \ + perl/sql/Wallet-Schema-0.10-SQLite.sql \ + perl/sql/wallet-1.3-update-duo.sql perl/t/data/README \ + perl/t/data/acl-command perl/t/data/duo/integration.json \ + perl/t/data/duo/integration-ldap.json \ + perl/t/data/duo/integration-radius.json \ + perl/t/data/duo/integration-rdp.json perl/t/data/duo/keys.json \ + perl/t/data/keytab-fake perl/t/data/keytab.conf \ perl/t/data/netdb-fake perl/t/data/netdb.conf perl/t/data/perl.conf \ perl/t/docs/pod-spelling.t perl/t/docs/pod.t perl/t/general/acl.t \ - perl/t/general/admin.t perl/t/general/config.t \ - perl/t/general/init.t perl/t/general/report.t \ - perl/t/general/server.t perl/t/lib/Util.pm perl/t/object/base.t \ - perl/t/object/duo.t perl/t/object/duo-ldap.t \ - perl/t/object/duo-pam.t perl/t/object/duo-radius.t \ + perl/t/general/admin.t perl/t/general/config.t \ + perl/t/general/init.t perl/t/general/report.t \ + perl/t/general/server.t perl/t/lib/Util.pm perl/t/object/base.t \ + perl/t/object/duo.t perl/t/object/duo-ldap.t \ + perl/t/object/duo-pam.t perl/t/object/duo-radius.t \ perl/t/object/duo-rdp.t perl/t/object/file.t perl/t/object/keytab.t \ - perl/t/object/password.t perl/t/object/wa-keyring.t \ - perl/t/policy/stanford.t perl/t/style/minimum-version.t \ + perl/t/object/password.t perl/t/object/wa-keyring.t \ + perl/t/policy/stanford.t perl/t/style/minimum-version.t \ perl/t/style/strict.t perl/t/util/kadmin.t perl/t/verifier/basic.t \ - perl/t/verifier/external.t perl/t/verifier/ldap-attr.t \ + perl/t/verifier/external.t perl/t/verifier/ldap-attr.t \ perl/t/verifier/nested.t perl/t/verifier/netdb.t # Directories that have to be created in builddir != srcdir builds before # copying PERL_FILES over. -PERL_DIRECTORIES = perl perl/lib perl/lib/Wallet perl/lib/Wallet/ACL \ - perl/lib/Wallet/ACL/Krb5 perl/lib/Wallet/ACL/LDAP \ - perl/lib/Wallet/ACL/LDAP/Attribute perl/lib/Wallet/ACL/NetDB \ - perl/lib/Wallet/Kadmin perl/lib/Wallet/Object \ - perl/lib/Wallet/Policy perl/lib/Wallet/Schema \ - perl/lib/Wallet/Schema/Result perl/sql perl/t perl/t/data \ +PERL_DIRECTORIES = perl perl/lib perl/lib/Wallet perl/lib/Wallet/ACL \ + perl/lib/Wallet/ACL/Krb5 perl/lib/Wallet/ACL/LDAP \ + perl/lib/Wallet/ACL/LDAP/Attribute perl/lib/Wallet/ACL/NetDB \ + perl/lib/Wallet/Kadmin perl/lib/Wallet/Object \ + perl/lib/Wallet/Policy perl/lib/Wallet/Schema \ + perl/lib/Wallet/Schema/Result perl/sql perl/t perl/t/data \ perl/t/data/duo perl/t/docs perl/t/general perl/t/lib perl/t/object \ perl/t/policy perl/t/style perl/t/util perl/t/verifier ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = .gitignore .travis.yml LICENSE README.md bootstrap \ - client/wallet.pod client/wallet-rekey.pod config/allow-extract \ - config/keytab config/keytab.acl config/wallet \ - config/wallet-report.acl docs/design contrib/README \ - contrib/ad-keytab contrib/ad-keytab.8 \ - contrib/commerzbank/wallet-history contrib/convert-srvtab-db \ - contrib/used-principals contrib/wallet-contacts \ - contrib/wallet-rekey-periodic contrib/wallet-rekey-periodic.8 \ - contrib/wallet-summary contrib/wallet-summary.8 \ - contrib/wallet-unknown-hosts contrib/wallet-unknown-hosts.8 \ +EXTRA_DIST = .gitignore .travis.yml LICENSE README.md bootstrap \ + client/wallet.pod client/wallet-rekey.pod config/allow-extract \ + config/keytab config/keytab.acl config/wallet \ + config/wallet-report.acl docs/design contrib/README \ + contrib/ad-keytab contrib/ad-keytab.8 \ + contrib/commerzbank/wallet-history contrib/convert-srvtab-db \ + contrib/used-principals contrib/wallet-contacts \ + contrib/wallet-rekey-periodic contrib/wallet-rekey-periodic.8 \ + contrib/wallet-summary contrib/wallet-summary.8 \ + contrib/wallet-unknown-hosts contrib/wallet-unknown-hosts.8 \ docs/design-acl docs/design-api docs/metadata docs/netdb-role-api \ docs/notes docs/objects-and-schemes docs/setup docs/stanford-naming \ - examples/stanford.conf server/keytab-backend.in \ - server/wallet-admin.in server/wallet-backend.in \ - server/wallet-report.in tests/README tests/TESTS \ + examples/stanford.conf server/keytab-backend.in \ + server/wallet-admin.in server/wallet-backend.in \ + server/wallet-report.in tests/README tests/TESTS \ tests/config/README tests/data/allow-extract tests/data/basic.conf \ tests/data/cmd-fake tests/data/cmd-wrapper tests/data/cppcheck.supp \ tests/data/fake-data tests/data/fake-kadmin tests/data/fake-keytab \ - tests/data/fake-keytab-2 tests/data/fake-keytab-foreign \ - tests/data/fake-keytab-merge tests/data/fake-keytab-old \ - tests/data/fake-keytab-partial \ + tests/data/fake-keytab-2 tests/data/fake-keytab-foreign \ + tests/data/fake-keytab-merge tests/data/fake-keytab-old \ + tests/data/fake-keytab-partial \ tests/data/fake-keytab-partial-result tests/data/fake-keytab-rekey \ - tests/data/fake-keytab-unknown tests/data/fake-srvtab \ + tests/data/fake-keytab-unknown tests/data/fake-srvtab \ tests/data/full.conf tests/data/perl.conf tests/data/wallet.conf \ - tests/docs/pod-spelling-t tests/docs/pod-t \ - tests/docs/spdx-license-t tests/perl/minimum-version-t \ - tests/perl/module-version-t tests/perl/strict-t \ + tests/docs/pod-spelling-t tests/docs/pod-t \ + tests/docs/spdx-license-t tests/perl/minimum-version-t \ + tests/perl/module-version-t tests/perl/strict-t \ tests/server/admin-t tests/server/backend-t tests/server/keytab-t \ - tests/server/report-t tests/style/obsolete-strings-t \ - tests/tap/kerberos.sh tests/tap/libtap.sh \ - tests/tap/perl/Test/RRA.pm tests/tap/perl/Test/RRA/Automake.pm \ - tests/tap/perl/Test/RRA/Config.pm \ - tests/tap/perl/Test/RRA/ModuleVersion.pm tests/tap/remctl.sh \ + tests/server/report-t tests/style/obsolete-strings-t \ + tests/tap/kerberos.sh tests/tap/libtap.sh \ + tests/tap/perl/Test/RRA.pm tests/tap/perl/Test/RRA/Automake.pm \ + tests/tap/perl/Test/RRA/Config.pm \ + tests/tap/perl/Test/RRA/ModuleVersion.pm tests/tap/remctl.sh \ tests/util/xmalloc-t $(PERL_FILES) # Supporting convenience libraries used by other targets. @@ -142,7 +142,7 @@ portable_libportable_a_SOURCES = portabl portable/uio.h portable_libportable_a_CPPFLAGS = $(KRB5_CPPFLAGS) portable_libportable_a_LIBADD = $(LIBOBJS) -util_libutil_a_SOURCES = util/macros.h util/messages-krb5.c \ +util_libutil_a_SOURCES = util/macros.h util/messages-krb5.c \ util/messages-krb5.h util/messages.c util/messages.h util/xmalloc.c \ util/xmalloc.h util_libutil_a_CPPFLAGS = $(KRB5_CPPFLAGS) @@ -150,21 +150,22 @@ util_libutil_a_CPPFLAGS = $(KRB5_CPPFLAG # The private library used by both wallet and wallet-rekey. noinst_LIBRARIES += client/libwallet.a client_libwallet_a_SOURCES = client/file.c client/internal.h client/keytab.c \ - client/krb5.c client/options.c client/remctl.c client/srvtab.c + client/krb5.c client/options.c client/remctl.c client/srvtab.c \ + client/checkfile.c client_libwallet_a_CPPFLAGS = $(REMCTL_CPPFLAGS) $(KRB5_CPPFLAGS) # The client and server programs. bin_PROGRAMS = client/wallet client/wallet-rekey sbin_SCRIPTS = server/keytab-backend server/wallet-admin \ server/wallet-backend server/wallet-report -client_wallet_CPPFLAGS = $(REMCTL_CPPFLAGS) $(KRB5_CPPFLAGS) -client_wallet_LDFLAGS = $(REMCTL_LDFLAGS) $(KRB5_LDFLAGS) +client_wallet_CPPFLAGS = $(REMCTL_CPPFLAGS) $(KRB5_CPPFLAGS) $(CRYPTO_CPPFLAGS) +client_wallet_LDFLAGS = $(REMCTL_LDFLAGS) $(KRB5_LDFLAGS) $(CRYPTO_LDFLAGS) client_wallet_LDADD = client/libwallet.a util/libutil.a \ - portable/libportable.a $(REMCTL_LIBS) $(KRB5_LIBS) -client_wallet_rekey_CPPFLAGS = $(REMCTL_CPPFLAGS) $(KRB5_CPPFLAGS) -client_wallet_rekey_LDFLAGS = $(REMCTL_LDFLAGS) $(KRB5_LDFLAGS) + portable/libportable.a $(REMCTL_LIBS) $(KRB5_LIBS) $(CRYPTO_LIBS) +client_wallet_rekey_CPPFLAGS = $(REMCTL_CPPFLAGS) $(KRB5_CPPFLAGS) $(CRYPTO_CPPFLAGS) +client_wallet_rekey_LDFLAGS = $(REMCTL_LDFLAGS) $(KRB5_LDFLAGS) $(CRYPTO_LDFLAGS) client_wallet_rekey_LDADD = client/libwallet.a util/libutil.a \ - portable/libportable.a $(REMCTL_LIBS) $(KRB5_LIBS) + portable/libportable.a $(REMCTL_LIBS) $(KRB5_LIBS) $(CRYPTO_LIBS) # The manual pages. dist_man_MANS = client/wallet.1 client/wallet-rekey.1 server/keytab-backend.8 \ @@ -189,18 +190,18 @@ dist_pkgdata_DATA = perl/sql/Wallet-Sche # compiler warnings enabled as possible. warnings: $(MAKE) V=0 CFLAGS='$(WARNINGS_CFLAGS) $(AM_CFLAGS)' \ - KRB5_CPPFLAGS='$(KRB5_CPPFLAGS_GCC)' + KRB5_CPPFLAGS='$(KRB5_CPPFLAGS_GCC)' $(MAKE) V=0 CFLAGS='$(WARNINGS_CFLAGS) $(AM_CFLAGS)' \ - KRB5_CPPFLAGS='$(KRB5_CPPFLAGS_GCC)' $(check_PROGRAMS) + KRB5_CPPFLAGS='$(KRB5_CPPFLAGS_GCC)' $(check_PROGRAMS) # Remove some additional files. CLEANFILES = perl/t/lib/Test/RRA.pm perl/t/lib/Test/RRA/Automake.pm \ perl/t/lib/Test/RRA/Config.pm server/keytab-backend \ server/wallet-admin server/wallet-backend server/wallet-report -MAINTAINERCLEANFILES = Makefile.in aclocal.m4 build-aux/compile \ - build-aux/depcomp build-aux/install-sh build-aux/missing \ - client/wallet.1 config.h.in config.h.in~ configure \ - contrib/wallet-report.8 server/keytab-backend.8 \ +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 build-aux/compile \ + build-aux/depcomp build-aux/install-sh build-aux/missing \ + client/wallet.1 config.h.in config.h.in~ configure \ + contrib/wallet-report.8 server/keytab-backend.8 \ server/wallet-admin.8 server/wallet-backend.8 server/wallet-report.8 # For each of the Perl scripts, we need to fill in the path to the Perl @@ -226,17 +227,17 @@ all-local: perl/blib/lib/Wallet/Config.p perl/blib/lib/Wallet/Config.pm: $(srcdir)/perl/lib/Wallet/Config.pm set -e; if [ x"$(builddir)" != x"$(srcdir)" ] ; then \ - for d in $(PERL_DIRECTORIES) ; do \ + for d in $(PERL_DIRECTORIES) ; do \ [ -d "$(builddir)/$$d" ] || mkdir "$(builddir)/$$d" ; \ - done ; \ - for f in $(PERL_FILES) ; do \ + done ; \ + for f in $(PERL_FILES) ; do \ cp "$(srcdir)/$$f" "$(builddir)/$$f" ; \ - done ; \ + done ; \ fi $(MKDIR_P) perl/t/lib/Test/RRA $(INSTALL_DATA) $(srcdir)/tests/tap/perl/Test/RRA.pm perl/t/lib/Test/ $(INSTALL_DATA) $(srcdir)/tests/tap/perl/Test/RRA/Config.pm \ - perl/t/lib/Test/RRA/ + perl/t/lib/Test/RRA/ cd perl && $(PERL) Build.PL $(WALLET_PERL_FLAGS) cd perl && ./Build @@ -251,13 +252,13 @@ perl/blib/lib/Wallet/Config.pm: $(srcdir install-data-local: set -e; flags= ; \ case "$(prefix)" in \ - */_inst) flags="--install_base $(prefix)" ;; \ + */_inst) flags="--install_base $(prefix)" ;; \ esac ; \ cd perl && ./Build install $$flags --destdir '$(DESTDIR)' clean-local: set -e; if [ -f "perl/Build" ] ; then \ - cd perl && ./Build realclean ; \ + cd perl && ./Build realclean ; \ fi # Remove the Autoconf cache. Remove the files that we copy over if and only @@ -265,9 +266,9 @@ clean-local: distclean-local: rm -rf autom4te.cache set -e; if [ x"$(builddir)" != x"$(srcdir)" ] ; then \ - for f in $(PERL_FILES) ; do \ + for f in $(PERL_FILES) ; do \ rm -f "$(builddir)/$$f" ; \ - done ; \ + done ; \ fi # The bits below are for the test suite, not for the main package. @@ -313,8 +314,8 @@ check-local: $(check_PROGRAMS) # Used by maintainers to check the source code with cppcheck. check-cppcheck: cd $(abs_top_srcdir) && cppcheck -q --error-exitcode=2 \ - --suppressions-list=tests/data/cppcheck.supp \ - --enable=warning,performance,portability,style . + --suppressions-list=tests/data/cppcheck.supp \ + --enable=warning,performance,portability,style . # Alas, we have to disable this check because there's no way to do an # uninstall from Perl. --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,9 @@ AC_CHECK_FUNCS([krb5_appdefault_string], AC_LIBOBJ([krb5-extra]) RRA_LIB_KRB5_RESTORE +dnl Probe for optional libraries +RRA_LIB_OPENSSL_OPTIONAL + dnl Probe for properties of the C library. AC_HEADER_STDBOOL AC_CHECK_HEADERS([strings.h sys/bitypes.h sys/uio.h sys/time.h syslog.h]) --- /dev/null +++ b/m4/openssl.m4 @@ -0,0 +1,115 @@ +dnl Find the compiler and linker flags for OpenSSL. +dnl +dnl Finds the compiler and linker flags for linking with both the OpenSSL SSL +dnl library and its crypto library. Provides the --with-openssl, +dnl --with-openssl-lib, and --with-openssl-include configure options to +dnl specify non-standard paths to the OpenSSL libraries. +dnl +dnl Provides the macro RRA_LIB_OPENSSL and sets the substitution variables +dnl OPENSSL_CPPFLAGS, OPENSSL_LDFLAGS, OPENSSL_LIBS, CRYPTO_CPPFLAGS, +dnl CRYPTO_LDFLAGS, and CRYPTO_LIBS. Also provides RRA_LIB_OPENSSL_SWITCH and +dnl RRA_LIB_CRYPTO_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the +dnl SSL or crypto libraries, saving the current values first, and +dnl RRA_LIB_OPENSSL_RESTORE and RRA_LIB_CRYPTO_RESTORE to restore those +dnl settings to before the last RRA_LIB_OPENSSL_SWITCH or +dnl RRA_LIB_CRYPTO_SWITCH. Defines HAVE_OPENSSL and sets rra_use_OPENSSL to +dnl true if the library is found. +dnl +dnl Provides the RRA_LIB_OPENSSL_OPTIONAL macro, which should be used if +dnl OpenSSL support is optional. This macro will still set the substitution +dnl variables and shell variables described above, but they'll be empty unless +dnl OpenSSL libraries are detected. HAVE_OPENSSL will be defined only if the +dnl library is found. +dnl +dnl Depends on RRA_ENABLE_REDUCED_DEPENDS and the lib-helper.m4 framework. +dnl +dnl The canonical version of this file is maintained in the rra-c-util +dnl package, available at . +dnl +dnl Written by Russ Allbery +dnl Copyright 2016, 2018 Russ Allbery +dnl Copyright 2010, 2013 +dnl The Board of Trustees of the Leland Stanford Junior University +dnl +dnl This file is free software; the authors give unlimited permission to copy +dnl and/or distribute it, with or without modifications, as long as this +dnl notice is preserved. +dnl +dnl SPDX-License-Identifier: FSFULLR + +dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to +dnl versions that include the SSL or crypto flags. Used as a wrapper, with +dnl RRA_LIB_OPENSSL_RESTORE or RRA_LIB_CRYPTO_RESTORE, around tests. +AC_DEFUN([RRA_LIB_OPENSSL_SWITCH], [RRA_LIB_HELPER_SWITCH([OPENSSL])]) +AC_DEFUN([RRA_LIB_CRYPTO_SWITCH], [RRA_LIB_HELPER_SWITCH([CRYPTO])]) + +dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before +dnl RRA_LIB_OPENSSL_SWITCH or RRA_LIB_CRYPTO_SWITCH were called). +AC_DEFUN([RRA_LIB_OPENSSL_RESTORE], [RRA_LIB_HELPER_RESTORE([OPENSSL])]) +AC_DEFUN([RRA_LIB_CRYPTO_RESTORE], [RRA_LIB_HELPER_RESTORE([CRYPTO])]) + +dnl Check for the OpenSSL and crypto libraries and assemble OPENSSL_LIBS and +dnl CRYPTO_LIBS. Helper function for _RRA_LIB_OPENSSL_INTERNAL. Must be +dnl called with RRA_LIB_OPENSSL_SWITCH enabled. +AC_DEFUN([_RRA_LIB_OPENSSL_INTERNAL_LIBS], +[rra_openssl_extra= + LIBS= + AS_IF([test x"$rra_reduced_depends" != xtrue], + [AC_SEARCH_LIBS([dlopen], [dl])]) + rra_openssl_extra="$LIBS" + LIBS="$rra_OPENSSL_save_LIBS" + AC_CHECK_LIB([crypto], [AES_cbc_encrypt], + [CRYPTO_LIBS="-lcrypto $rra_openssl_extra"], + [AS_IF([test x"$1" = xtrue], + [AC_MSG_ERROR([cannot find usable OpenSSL crypto library])])], + [$rra_openssl_extra]) + AS_IF([test x"$rra_reduced_depends" = xtrue], + [AC_CHECK_LIB([ssl], [SSL_accept], [OPENSSL_LIBS=-lssl], + [AS_IF([test x"$1" = xtrue], + [AC_MSG_ERROR([cannot find usable OpenSSL library])])])], + [AC_CHECK_LIB([ssl], [SSL_accept], + [OPENSSL_LIBS="-lssl $CRYPTO_LIBS"], + [AS_IF([test x"$1" = xtrue], + [AC_MSG_ERROR([cannot find usable OpenSSL library])])], + [$CRYPTO_LIBS])])]) + +dnl Checks if the OpenSSL header and OpenSSL and crypto libraries are present. +dnl The single argument, if "true", says to fail if the OpenSSL SSL library +dnl could not be found. +AC_DEFUN([_RRA_LIB_OPENSSL_INTERNAL], +[AC_REQUIRE([RRA_ENABLE_REDUCED_DEPENDS]) + RRA_LIB_HELPER_PATHS([OPENSSL]) + CRYPTO_CPPFLAGS="$OPENSSL_CPPFLAGS" + CRYPTO_LDFLAGS="$OPENSSL_LDFLAGS" + CRYPTO_LIBS= + AC_SUBST([CRYPTO_CPPFLAGS]) + AC_SUBST([CRYPTO_LDFLAGS]) + AC_SUBST([CRYPTO_LIBS]) + RRA_LIB_OPENSSL_SWITCH + AC_CHECK_HEADER([openssl/ssl.h], + [_RRA_LIB_OPENSSL_INTERNAL_LIBS([$1])], + [AS_IF([test x"$1" = xtrue], + [AC_MSG_ERROR([cannot find usable OpenSSL header])])]) + RRA_LIB_OPENSSL_RESTORE]) + +dnl The main macro for packages with mandatory OpenSSL support. +AC_DEFUN([RRA_LIB_OPENSSL], +[RRA_LIB_HELPER_VAR_INIT([OPENSSL]) + RRA_LIB_HELPER_WITH([openssl], [OpenSSL], [OPENSSL]) + _RRA_LIB_OPENSSL_INTERNAL([true]) + rra_use_OPENSSL=true + AC_DEFINE([HAVE_OPENSSL], 1, [Define if libssl is available.])]) + +dnl The main macro for packages with optional OpenSSL support. +AC_DEFUN([RRA_LIB_OPENSSL_OPTIONAL], +[RRA_LIB_HELPER_VAR_INIT([OPENSSL]) + RRA_LIB_HELPER_WITH_OPTIONAL([openssl], [OpenSSL], [OPENSSL]) + AS_IF([test x"$rra_use_OPENSSL" != xfalse], + [AS_IF([test x"$rra_use_OPENSSL" = xtrue], + [_RRA_LIB_OPENSSL_INTERNAL([true])], + [_RRA_LIB_OPENSSL_INTERNAL([false])])]) + AS_IF([test x"$OPENSSL_LIBS" = x], + [RRA_LIB_HELPER_VAR_CLEAR([OPENSSL]) + RRA_LIB_HELPER_VAR_CLEAR([CRYPTO])], + [rra_use_OPENSSL=true + AC_DEFINE([HAVE_OPENSSL], 1, [Define if libssl is available.])])]) --- /dev/null +++ b/m4/lib-helper.m4 @@ -0,0 +1,149 @@ +dnl Helper functions to manage compiler variables. +dnl +dnl These are a wide variety of helper macros to make it easier to construct +dnl standard macros to probe for a library and to set library-specific +dnl CPPFLAGS, LDFLAGS, and LIBS shell substitution variables. Most of them +dnl take as one of the arguments the prefix string to use for variables, which +dnl is usually something like "KRB5" or "GSSAPI". +dnl +dnl Depends on RRA_SET_LDFLAGS. +dnl +dnl The canonical version of this file is maintained in the rra-c-util +dnl package, available at . +dnl +dnl Written by Russ Allbery +dnl Copyright 2018 Russ Allbery +dnl Copyright 2011, 2013 +dnl The Board of Trustees of the Leland Stanford Junior University +dnl +dnl This file is free software; the authors give unlimited permission to copy +dnl and/or distribute it, with or without modifications, as long as this +dnl notice is preserved. +dnl +dnl SPDX-License-Identifier: FSFULLR + +dnl Add the library flags to the default compiler flags and then remove them. +dnl +dnl To use these macros, pass the prefix string used for the variables as the +dnl only argument. For example, to use these for a library with KRB5 as a +dnl prefix, one would use: +dnl +dnl AC_DEFUN([RRA_LIB_KRB5_SWITCH], [RRA_LIB_HELPER_SWITCH([KRB5])]) +dnl AC_DEFUN([RRA_LIB_KRB5_RESTORE], [RRA_LIB_HELPER_RESTORE([KRB5])]) +dnl +dnl Then, wrap checks for library features with RRA_LIB_KRB5_SWITCH and +dnl RRA_LIB_KRB5_RESTORE. +AC_DEFUN([RRA_LIB_HELPER_SWITCH], +[rra_$1[]_save_CPPFLAGS="$CPPFLAGS" + rra_$1[]_save_LDFLAGS="$LDFLAGS" + rra_$1[]_save_LIBS="$LIBS" + CPPFLAGS="$$1[]_CPPFLAGS $CPPFLAGS" + LDFLAGS="$$1[]_LDFLAGS $LDFLAGS" + LIBS="$$1[]_LIBS $LIBS"]) + +AC_DEFUN([RRA_LIB_HELPER_RESTORE], +[CPPFLAGS="$rra_$1[]_save_CPPFLAGS" + LDFLAGS="$rra_$1[]_save_LDFLAGS" + LIBS="$rra_$1[]_save_LIBS"]) + +dnl Given _root, _libdir, and _includedir variables set for a library (set by +dnl RRA_LIB_HELPER_WITH*), set the LDFLAGS and CPPFLAGS variables for that +dnl library accordingly. Takes the variable prefix as the only argument. +AC_DEFUN([RRA_LIB_HELPER_PATHS], +[AS_IF([test x"$rra_$1[]_libdir" != x], + [$1[]_LDFLAGS="-L$rra_$1[]_libdir"], + [AS_IF([test x"$rra_$1[]_root" != x], + [RRA_SET_LDFLAGS([$1][_LDFLAGS], [${rra_$1[]_root}])])]) + AS_IF([test x"$rra_$1[]_includedir" != x], + [$1[]_CPPFLAGS="-I$rra_$1[]_includedir"], + [AS_IF([test x"$rra_$1[]_root" != x], + [AS_IF([test x"$rra_$1[]_root" != x/usr], + [$1[]_CPPFLAGS="-I${rra_$1[]_root}/include"])])])]) + +dnl Check whether a library works. This is used as a sanity check on the +dnl results of *-config shell scripts. Takes four arguments; the first, if +dnl "true", says that a working library is mandatory and errors out if it +dnl doesn't. The second is the variable prefix. The third is a function to +dnl look for that should be in the libraries. The fourth is the +dnl human-readable name of the library for error messages. +AC_DEFUN([RRA_LIB_HELPER_CHECK], +[RRA_LIB_HELPER_SWITCH([$2]) + AC_CHECK_FUNC([$3], [], + [AS_IF([test x"$1" = xtrue], + [AC_MSG_FAILURE([unable to link with $4 library])]) + $2[]_CPPFLAGS= + $2[]_LDFLAGS= + $2[]_LIBS=]) + RRA_LIB_HELPER_RESTORE([$2])]) + +dnl Initialize the variables used by a library probe and set the appropriate +dnl ones as substitution variables. Takes the library variable prefix as its +dnl only argument. +AC_DEFUN([RRA_LIB_HELPER_VAR_INIT], +[rra_$1[]_root= + rra_$1[]_libdir= + rra_$1[]_includedir= + rra_use_$1= + $1[]_CPPFLAGS= + $1[]_LDFLAGS= + $1[]_LIBS= + AC_SUBST([$1][_CPPFLAGS]) + AC_SUBST([$1][_LDFLAGS]) + AC_SUBST([$1][_LIBS])]) + +dnl Unset all of the variables used by a library probe. Used with the +dnl _OPTIONAL versions of header probes when a header or library wasn't found +dnl and therefore the library isn't usable. +AC_DEFUN([RRA_LIB_HELPER_VAR_CLEAR], +[$1[]_CPPFLAGS= + $1[]_LDFLAGS= + $1[]_LIBS=]) + +dnl Handles --with options for a non-optional library. First argument is the +dnl base for the switch names. Second argument is the short description. +dnl Third argument is the variable prefix. The variables set are used by +dnl RRA_LIB_HELPER_PATHS. +AC_DEFUN([RRA_LIB_HELPER_WITH], +[AC_ARG_WITH([$1], + [AS_HELP_STRING([--with-][$1][=DIR], + [Location of $2 headers and libraries])], + [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], + [rra_$3[]_root="$withval"])]) + AC_ARG_WITH([$1][-include], + [AS_HELP_STRING([--with-][$1][-include=DIR], + [Location of $2 headers])], + [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], + [rra_$3[]_includedir="$withval"])]) + AC_ARG_WITH([$1][-lib], + [AS_HELP_STRING([--with-][$1][-lib=DIR], + [Location of $2 libraries])], + [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], + [rra_$3[]_libdir="$withval"])])]) + +dnl Handles --with options for an optional library, so --with- can +dnl cause the checks to be skipped entirely or become mandatory. Sets an +dnl rra_use_PREFIX variable to true or false if the library is explicitly +dnl enabled or disabled. +dnl +dnl First argument is the base for the switch names. Second argument is the +dnl short description. Third argument is the variable prefix. +dnl +dnl The variables set are used by RRA_LIB_HELPER_PATHS. +AC_DEFUN([RRA_LIB_HELPER_WITH_OPTIONAL], +[AC_ARG_WITH([$1], + [AS_HELP_STRING([--with-][$1][@<:@=DIR@:>@], + [Location of $2 headers and libraries])], + [AS_IF([test x"$withval" = xno], + [rra_use_$3=false], + [AS_IF([test x"$withval" != xyes], [rra_$3[]_root="$withval"]) + rra_use_$3=true])]) + AC_ARG_WITH([$1][-include], + [AS_HELP_STRING([--with-][$1][-include=DIR], + [Location of $2 headers])], + [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], + [rra_$3[]_includedir="$withval"])]) + AC_ARG_WITH([$1][-lib], + [AS_HELP_STRING([--with-][$1][-lib=DIR], + [Location of $2 libraries])], + [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], + [rra_$3[]_libdir="$withval"])])])